Merge
authorduke
Wed, 05 Jul 2017 22:42:01 +0200
changeset 43150 1c9922f121ff
parent 43149 047a57b0839a (current diff)
parent 43129 dca22f522449 (diff)
child 43151 d7034ff7f8e2
Merge
jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java
jdk/test/java/rmi/registry/readTest/readTest.java
jdk/test/java/rmi/registry/readTest/readTest.sh
jdk/test/java/rmi/testlibrary/REGISTRY.java
jdk/test/lib/security/SecurityTools.java
jdk/test/tools/jar/mmrjar/ConcealedPackage.java
jdk/test/tools/jmod/hashes/src/m1/module-info.java
jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java
jdk/test/tools/jmod/hashes/src/m2/module-info.java
jdk/test/tools/jmod/hashes/src/m2/org/m2/Util.java
jdk/test/tools/jmod/hashes/src/m3/module-info.java
jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java
jdk/test/tools/jmod/hashes/src/org.bar/module-info.java
jdk/test/tools/jmod/hashes/src/org.foo/module-info.java
--- a/.hgtags-top-repo	Tue Jan 17 07:41:04 2017 +0100
+++ b/.hgtags-top-repo	Wed Jul 05 22:42:01 2017 +0200
@@ -394,3 +394,4 @@
 b119012d1c2ab2570fe8718633840d0c1f1f441d jdk-9+149
 6234069ff9789f7582e1faa32cb6283cbd1a5a2d jdk-9+150
 71a766d4c18041a7f833ee22823125b02e1a7f1e jdk-9+151
+ef056360ddf3977d7d2ddbeb456a4d612d19ea05 jdk-9+152
--- a/common/autoconf/basics.m4	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/basics.m4	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -1011,6 +1011,8 @@
   # Test which kind of tar was found
   if test "x$($TAR --version | $GREP "GNU tar")" != "x"; then
     TAR_TYPE="gnu"
+  elif test "x$($TAR --version | $GREP "bsdtar")" != "x"; then
+    TAR_TYPE="bsd"
   elif test "x$($TAR -v | $GREP "bsdtar")" != "x"; then
     TAR_TYPE="bsd"
   elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
@@ -1038,12 +1040,36 @@
   AC_SUBST(TAR_SUPPORTS_TRANSFORM)
 ])
 
+AC_DEFUN([BASIC_CHECK_GREP],
+[
+  # Test that grep supports -Fx with a list of pattern which includes null pattern.
+  # This is a problem for the grep resident on AIX.
+  AC_MSG_CHECKING([that grep ($GREP) -Fx handles empty lines in the pattern list correctly])
+  # Multiple subsequent spaces..
+  STACK_SPACES='aaa   bbb   ccc'
+  # ..converted to subsequent newlines, causes STACK_LIST to be a list with some empty
+  # patterns in it.
+  STACK_LIST=${STACK_SPACES// /$'\n'}
+  NEEDLE_SPACES='ccc bbb aaa'
+  NEEDLE_LIST=${NEEDLE_SPACES// /$'\n'}
+  RESULT="$($GREP -Fvx "$STACK_LIST" <<< "$NEEDLE_LIST")"
+  if test "x$RESULT" == "x"; then
+    AC_MSG_RESULT([yes])
+  else
+    if test "x$OPENJDK_TARGET_OS" = "xaix"; then
+      ADDINFO="Please make sure you use GNU grep, usually found at /opt/freeware/bin."
+    fi
+    AC_MSG_ERROR([grep does not handle -Fx correctly. ${ADDINFO}])
+  fi
+])
+
 AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
 [
   BASIC_CHECK_GNU_MAKE
 
   BASIC_CHECK_FIND_DELETE
   BASIC_CHECK_TAR
+  BASIC_CHECK_GREP
 
   # These tools might not be installed by default,
   # need hint on how to install them.
--- a/common/autoconf/buildjdk-spec.gmk.in	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/buildjdk-spec.gmk.in	Wed Jul 05 22:42:01 2017 +0200
@@ -68,7 +68,6 @@
 CFLAGS_JDKEXE := @OPENJDK_BUILD_CFLAGS_JDKEXE@
 CXXFLAGS_JDKEXE := @OPENJDK_BUILD_CXXFLAGS_JDKEXE@
 LDFLAGS_JDKEXE := @OPENJDK_BUILD_LDFLAGS_JDKEXE@
-OPENJDK_TARGET_CPU_JLI_CFLAGS := @OPENJDK_BUILD_CPU_JLI_CFLAGS@
 
 JVM_CFLAGS := @OPENJDK_BUILD_JVM_CFLAGS@
 JVM_LDFLAGS := @OPENJDK_BUILD_JVM_LDFLAGS@
--- a/common/autoconf/flags.m4	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/flags.m4	Wed Jul 05 22:42:01 2017 +0200
@@ -815,11 +815,6 @@
     $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__"
   fi
 
-  if test "x$OPENJDK_TARGET_OS" = xsolaris; then
-    $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__"
-    $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__"
-  fi
-
   $2CFLAGS_JDK="${$2CFLAGS_JDK} ${$2EXTRA_CFLAGS}"
   $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2EXTRA_CXXFLAGS}"
   $2LDFLAGS_JDK="${$2LDFLAGS_JDK} ${$2EXTRA_LDFLAGS}"
--- a/common/autoconf/generated-configure.sh	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 22:42:01 2017 +0200
@@ -3564,7 +3564,7 @@
 
 # Include these first...
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -3731,6 +3731,8 @@
 
 
 
+
+
 # Check if build directory is on local disk. If not possible to determine,
 # we prefer to claim it's local.
 # Argument 1: directory to test
@@ -4122,7 +4124,7 @@
 
 
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -4237,6 +4239,17 @@
   esac
 }
 
+brew_help() {
+  case $1 in
+    openjdk)
+      PKGHANDLER_COMMAND="brew cask install java" ;;
+    freetype)
+      PKGHANDLER_COMMAND="brew install freetype" ;;
+    ccache)
+      PKGHANDLER_COMMAND="brew install ccache" ;;
+  esac
+}
+
 port_help() {
   PKGHANDLER_COMMAND=""
 }
@@ -4362,7 +4375,7 @@
 
 
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -4667,7 +4680,7 @@
 
 
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -5167,7 +5180,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1483542685
+DATE_WHEN_GENERATED=1484571183
 
 ###############################################################################
 #
@@ -17544,7 +17557,7 @@
 
 # Must be done before we can call HELP_MSG_MISSING_DEPENDENCY.
 
-  for ac_prog in apt-get yum port pkgutil pkgadd
+  for ac_prog in apt-get yum brew port pkgutil pkgadd
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -21209,6 +21222,8 @@
   # Test which kind of tar was found
   if test "x$($TAR --version | $GREP "GNU tar")" != "x"; then
     TAR_TYPE="gnu"
+  elif test "x$($TAR --version | $GREP "bsdtar")" != "x"; then
+    TAR_TYPE="bsd"
   elif test "x$($TAR -v | $GREP "bsdtar")" != "x"; then
     TAR_TYPE="bsd"
   elif test "x$OPENJDK_BUILD_OS" = "xsolaris"; then
@@ -21238,6 +21253,29 @@
 
 
 
+  # Test that grep supports -Fx with a list of pattern which includes null pattern.
+  # This is a problem for the grep resident on AIX.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking that grep ($GREP) -Fx handles empty lines in the pattern list correctly" >&5
+$as_echo_n "checking that grep ($GREP) -Fx handles empty lines in the pattern list correctly... " >&6; }
+  # Multiple subsequent spaces..
+  STACK_SPACES='aaa   bbb   ccc'
+  # ..converted to subsequent newlines, causes STACK_LIST to be a list with some empty
+  # patterns in it.
+  STACK_LIST=${STACK_SPACES// /$'\n'}
+  NEEDLE_SPACES='ccc bbb aaa'
+  NEEDLE_LIST=${NEEDLE_SPACES// /$'\n'}
+  RESULT="$($GREP -Fvx "$STACK_LIST" <<< "$NEEDLE_LIST")"
+  if test "x$RESULT" == "x"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    if test "x$OPENJDK_TARGET_OS" = "xaix"; then
+      ADDINFO="Please make sure you use GNU grep, usually found at /opt/freeware/bin."
+    fi
+    as_fn_error $? "grep does not handle -Fx correctly. ${ADDINFO}" "$LINENO" 5
+  fi
+
+
   # These tools might not be installed by default,
   # need hint on how to install them.
 
@@ -24359,15 +24397,13 @@
 fi
 
 
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if packaged modules are kept" >&5
+$as_echo_n "checking if packaged modules are kept... " >&6; }
   if test "x$enable_keep_packaged_modules" = "xyes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if packaged modules are kept" >&5
-$as_echo_n "checking if packaged modules are kept... " >&6; }
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
     JLINK_KEEP_PACKAGED_MODULES=true
   elif test "x$enable_keep_packaged_modules" = "xno"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if packaged modules are kept" >&5
-$as_echo_n "checking if packaged modules are kept... " >&6; }
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
     JLINK_KEEP_PACKAGED_MODULES=false
@@ -24376,6 +24412,8 @@
 $as_echo "yes (default)" >&6; }
     JLINK_KEEP_PACKAGED_MODULES=true
   else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: error" >&5
+$as_echo "error" >&6; }
     as_fn_error $? "--enable-keep-packaged-modules accepts no argument" "$LINENO" 5
   fi
 
@@ -29942,6 +29980,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -33235,6 +33275,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -34534,6 +34576,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -48601,6 +48645,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -48762,6 +48808,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -49897,11 +49945,6 @@
     CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__"
   fi
 
-  if test "x$OPENJDK_TARGET_OS" = xsolaris; then
-    CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__"
-    CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__"
-  fi
-
   CFLAGS_JDK="${CFLAGS_JDK} ${EXTRA_CFLAGS}"
   CXXFLAGS_JDK="${CXXFLAGS_JDK} ${EXTRA_CXXFLAGS}"
   LDFLAGS_JDK="${LDFLAGS_JDK} ${EXTRA_LDFLAGS}"
@@ -50720,11 +50763,6 @@
     OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__"
   fi
 
-  if test "x$OPENJDK_TARGET_OS" = xsolaris; then
-    OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__"
-    OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__"
-  fi
-
   OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CFLAGS}"
   OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CXXFLAGS}"
   OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_LDFLAGS}"
@@ -52844,6 +52882,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -56649,6 +56689,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -56721,6 +56763,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -56864,6 +56908,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -60741,6 +60787,345 @@
   fi
 
           fi
+          if test "x$FOUND_FREETYPE" != xyes; then
+            FREETYPE_BASE_DIR="$SYSROOT/usr/local"
+
+  POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
+  POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib"
+  METHOD="well-known location"
+
+  # Let's start with an optimistic view of the world :-)
+  FOUND_FREETYPE=yes
+
+  # First look for the canonical freetype main include file ft2build.h.
+  if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+    # Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
+    if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+      # Fail.
+      FOUND_FREETYPE=no
+    fi
+  fi
+
+  if test "x$FOUND_FREETYPE" = xyes; then
+    # Include file found, let's continue the sanity check.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+
+    # Reset to default value
+    FREETYPE_BASE_NAME=freetype
+    FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+    if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+      if test "x$OPENJDK_TARGET_OS" = xmacosx \
+          && test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
+        # On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
+        # for the .6 version explicitly.
+        FREETYPE_BASE_NAME=freetype.6
+        FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Compensating for missing symlink by using version 6 explicitly" >&5
+$as_echo "$as_me: Compensating for missing symlink by using version 6 explicitly" >&6;}
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+        FOUND_FREETYPE=no
+      fi
+    else
+      if test "x$OPENJDK_TARGET_OS" = xwindows; then
+        # On Windows, we will need both .lib and .dll file.
+        if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
+          { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&6;}
+          FOUND_FREETYPE=no
+        fi
+      elif test "x$OPENJDK_TARGET_OS" = xsolaris \
+          && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
+        # Found lib in isa dir, use that instead.
+        POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&5
+$as_echo "$as_me: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&6;}
+      fi
+    fi
+  fi
+
+  if test "x$FOUND_FREETYPE" = xyes; then
+
+  # Only process if variable expands to non-empty
+
+  if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+  fi
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+    else
+      # We're on a unix platform. Hooray! :)
+      path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+      has_space=`$ECHO "$path" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+      fi
+
+      # Use eval to expand a potential ~
+      eval path="$path"
+      if test ! -f "$path" && test ! -d "$path"; then
+        as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+      fi
+
+      if test -d "$path"; then
+        POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+      else
+        dir="`$DIRNAME "$path"`"
+        base="`$BASENAME "$path"`"
+        POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+      fi
+    fi
+  fi
+
+
+  # Only process if variable expands to non-empty
+
+  if test "x$POTENTIAL_FREETYPE_LIB_PATH" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$POTENTIAL_FREETYPE_LIB_PATH"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+  fi
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$POTENTIAL_FREETYPE_LIB_PATH"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+    else
+      # We're on a unix platform. Hooray! :)
+      path="$POTENTIAL_FREETYPE_LIB_PATH"
+      has_space=`$ECHO "$path" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+      fi
+
+      # Use eval to expand a potential ~
+      eval path="$path"
+      if test ! -f "$path" && test ! -d "$path"; then
+        as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+      fi
+
+      if test -d "$path"; then
+        POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+      else
+        dir="`$DIRNAME "$path"`"
+        base="`$BASENAME "$path"`"
+        POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+      fi
+    fi
+  fi
+
+
+    FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+    FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+  fi
+
+          fi
 
           if test "x$OPENJDK_TARGET_OS" = xmacosx; then
             if test "x$FOUND_FREETYPE" != xyes; then
@@ -62122,6 +62507,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -62477,6 +62864,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -62682,6 +63071,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -62870,6 +63261,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -62949,6 +63342,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -64058,6 +64453,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -64142,6 +64539,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
--- a/common/autoconf/help.m4	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/help.m4	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 
 AC_DEFUN_ONCE([HELP_SETUP_DEPENDENCY_HELP],
 [
-  AC_CHECK_PROGS(PKGHANDLER, apt-get yum port pkgutil pkgadd)
+  AC_CHECK_PROGS(PKGHANDLER, apt-get yum brew port pkgutil pkgadd)
 ])
 
 AC_DEFUN([HELP_MSG_MISSING_DEPENDENCY],
@@ -46,6 +46,8 @@
         apt_help     $MISSING_DEPENDENCY ;;
       yum)
         yum_help     $MISSING_DEPENDENCY ;;
+      brew)
+        brew_help    $MISSING_DEPENDENCY ;;
       port)
         port_help    $MISSING_DEPENDENCY ;;
       pkgutil)
@@ -147,6 +149,17 @@
   esac
 }
 
+brew_help() {
+  case $1 in
+    openjdk)
+      PKGHANDLER_COMMAND="brew cask install java" ;;
+    freetype)
+      PKGHANDLER_COMMAND="brew install freetype" ;;
+    ccache)
+      PKGHANDLER_COMMAND="brew install ccache" ;;
+  esac
+}
+
 port_help() {
   PKGHANDLER_COMMAND=""
 }
--- a/common/autoconf/jdk-options.m4	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/jdk-options.m4	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -382,18 +382,18 @@
   AC_ARG_ENABLE([keep-packaged-modules], [AS_HELP_STRING([--disable-keep-packaged-modules],
     [Do not keep packaged modules in jdk image @<:@enable@:>@])])
 
+  AC_MSG_CHECKING([if packaged modules are kept])
   if test "x$enable_keep_packaged_modules" = "xyes"; then
-    AC_MSG_CHECKING([if packaged modules are kept])
     AC_MSG_RESULT([yes])
     JLINK_KEEP_PACKAGED_MODULES=true
   elif test "x$enable_keep_packaged_modules" = "xno"; then
-    AC_MSG_CHECKING([if packaged modules are kept])
     AC_MSG_RESULT([no])
     JLINK_KEEP_PACKAGED_MODULES=false
   elif test "x$enable_keep_packaged_modules" = "x"; then
     AC_MSG_RESULT([yes (default)])
     JLINK_KEEP_PACKAGED_MODULES=true
   else
+    AC_MSG_RESULT([error])
     AC_MSG_ERROR([--enable-keep-packaged-modules accepts no argument])
   fi
 
--- a/common/autoconf/lib-freetype.m4	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/lib-freetype.m4	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -348,6 +348,10 @@
             FREETYPE_BASE_DIR="$SYSROOT/usr/X11"
             LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
           fi
+          if test "x$FOUND_FREETYPE" != xyes; then
+            FREETYPE_BASE_DIR="$SYSROOT/usr/local"
+            LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
+          fi
 
           if test "x$OPENJDK_TARGET_OS" = xmacosx; then
             if test "x$FOUND_FREETYPE" != xyes; then
--- a/common/autoconf/spec.gmk.in	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 22:42:01 2017 +0200
@@ -274,8 +274,6 @@
 CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
 BUILDJDK_OUTPUTDIR=$(BUILD_OUTPUT)/buildjdk
 
-BUILD_HOTSPOT=@BUILD_HOTSPOT@
-
 BUILD_FAILURE_HANDLER := @BUILD_FAILURE_HANDLER@
 
 ENABLE_GENERATE_CLASSLIST := @ENABLE_GENERATE_CLASSLIST@
@@ -642,7 +640,6 @@
 NICE:=@NICE@
 PATCH:=@PATCH@
 PRINTF:=@PRINTF@
-PWD:=@THEPWDCMD@
 RM:=@RM@
 RMDIR:=@RMDIR@
 SED:=@SED@
@@ -778,11 +775,18 @@
 # Images directory definitions
 JDK_IMAGE_SUBDIR:=jdk
 JRE_IMAGE_SUBDIR:=jre
+JRE_COMPACT1_IMAGE_SUBDIR := jre-compact1
+JRE_COMPACT2_IMAGE_SUBDIR := jre-compact2
+JRE_COMPACT3_IMAGE_SUBDIR := jre-compact3
 
 # Colon left out to be able to override output dir for bootcycle-images
 JDK_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(JDK_IMAGE_SUBDIR)
 JRE_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(JRE_IMAGE_SUBDIR)
 
+JRE_COMPACT1_IMAGE_DIR := $(IMAGES_OUTPUTDIR)/$(JRE_COMPACT1_IMAGE_SUBDIR)
+JRE_COMPACT2_IMAGE_DIR := $(IMAGES_OUTPUTDIR)/$(JRE_COMPACT2_IMAGE_SUBDIR)
+JRE_COMPACT3_IMAGE_DIR := $(IMAGES_OUTPUTDIR)/$(JRE_COMPACT3_IMAGE_SUBDIR)
+
 # Test image, as above
 TEST_IMAGE_SUBDIR:=test
 TEST_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(TEST_IMAGE_SUBDIR)
@@ -818,6 +822,12 @@
 endif
 JDK_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART).tar.gz
 JRE_BUNDLE_NAME := jre-$(BASE_NAME)_bin$(DEBUG_PART).tar.gz
+JRE_COMPACT1_BUNDLE_NAME := \
+    jre-$(VERSION_SHORT)+$(VERSION_BUILD)-compact1_$(OPENJDK_TARGET_BUNDLE_PLATFORM)_bin$(DEBUG_PART).tar.gz
+JRE_COMPACT2_BUNDLE_NAME := \
+    jre-$(VERSION_SHORT)+$(VERSION_BUILD)-compact2_$(OPENJDK_TARGET_BUNDLE_PLATFORM)_bin$(DEBUG_PART).tar.gz
+JRE_COMPACT3_BUNDLE_NAME := \
+    jre-$(VERSION_SHORT)+$(VERSION_BUILD)-compact3_$(OPENJDK_TARGET_BUNDLE_PLATFORM)_bin$(DEBUG_PART).tar.gz
 JDK_SYMBOLS_BUNDLE_NAME := jdk-$(BASE_NAME)_bin$(DEBUG_PART)-symbols.tar.gz
 JRE_SYMBOLS_BUNDLE_NAME := jre-$(BASE_NAME)_bin$(DEBUG_PART)-symbols.tar.gz
 ifeq ($(OPENJDK_TARGET_OS), windows)
--- a/common/conf/jib-profiles.js	Tue Jan 17 07:41:04 2017 +0100
+++ b/common/conf/jib-profiles.js	Wed Jul 05 22:42:01 2017 +0200
@@ -501,7 +501,7 @@
     // extra default target.
     var openOnlyProfilesExtra = {
         "linux-x86-open": {
-            default_make_targets: "profiles",
+            default_make_targets: "profiles-bundles",
             configure_args: "--with-jvm-variants=client,server"
         }
     };
@@ -587,6 +587,7 @@
             ],
             work_dir: input.get("src.full", "install_path") + "/test",
             environment: {
+                "JT_JAVA": common.boot_jdk_home,
                 "PRODUCT_HOME": input.get(testedProfile + ".jdk", "home_path"),
                 "TEST_IMAGE_DIR": input.get(testedProfile + ".test", "home_path"),
                 "TEST_OUTPUT_DIR": input.src_top_dir
@@ -710,10 +711,15 @@
                     local: "bundles/\\(jdk.*bin.tar.gz\\)",
                     remote: "bundles/openjdk/GPL/profile/linux-x86/\\1",
                 },
+                jdk_symbols: {
+                    local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
+                    remote: "bundles/openjdk/GPL/profile/linux-x86/\\1",
+                },
                 jre: {
-                    local: "bundles/\\(jre.*[0-9]_linux-x86_bin.tar.gz\\)",
+                    // This regexp needs to not match the compact* files below
+                    local: "bundles/\\(jre.*[+][0-9]\\{1,\\}_linux-x86_bin.tar.gz\\)",
                     remote: "bundles/openjdk/GPL/profile/linux-x86/\\1",
-                },/* The build does not create these
+                },
                 jre_compact1: {
                     local: "bundles/\\(jre.*-compact1_linux-x86_bin.tar.gz\\)",
                     remote: "bundles/openjdk/GPL/profile/linux-x86/\\1",
@@ -725,7 +731,7 @@
                 jre_compact3: {
                     local: "bundles/\\(jre.*-compact3_linux-x86_bin.tar.gz\\)",
                     remote: "bundles/openjdk/GPL/profile/linux-x86/\\1",
-                },*/
+                },
             }
         },
 
@@ -864,7 +870,7 @@
         jtreg: {
             server: "javare",
             revision: "4.2",
-            build_number: "b04",
+            build_number: "b05",
             checksum_file: "MD5_VALUES",
             file: "jtreg_bin-4.2.zip",
             environment_name: "JT_HOME",
--- a/corba/.hgtags	Tue Jan 17 07:41:04 2017 +0100
+++ b/corba/.hgtags	Wed Jul 05 22:42:01 2017 +0200
@@ -394,3 +394,4 @@
 00b19338e505690abe93d5995ed74a473d969c2c jdk-9+149
 9205e980062a5c4530b51021c6e274025f4ccbdf jdk-9+150
 77f827f5bbad3ef795664bc675f72d98d156b9f8 jdk-9+151
+ff8cb43c07c069b1debdee44cb88ca22db1ec757 jdk-9+152
--- a/hotspot/.hgtags	Tue Jan 17 07:41:04 2017 +0100
+++ b/hotspot/.hgtags	Wed Jul 05 22:42:01 2017 +0200
@@ -554,3 +554,4 @@
 30e1996bd55da36183434f24ed964adebf9ca71e jdk-9+149
 98fe046473c90204cbc9b34c512b9fc10dfb8479 jdk-9+150
 2a2ac7d9f52c8cb2b80077e515b5840b947e640c jdk-9+151
+31f1d26c60df7b2e516a4f84160d76ba017d4e09 jdk-9+152
--- a/jaxp/.hgtags	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/.hgtags	Wed Jul 05 22:42:01 2017 +0200
@@ -394,3 +394,4 @@
 5978df8bfa3894f2b3d07b7256f25f78dffb1f9c jdk-9+149
 f85154af719f99a3b4d81b67a8b4c18a650d10f9 jdk-9+150
 13c6906bfc861d99dc35a19c80b7a99f0b0ac58d jdk-9+151
+7e3da313b1746578da648155e37dd8526e83153d jdk-9+152
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/DOM2SAX.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/DOM2SAX.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -17,20 +17,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/*
- * $Id: DOM2SAX.java,v 1.2.4.1 2005/09/06 11:52:46 pvedula Exp $
- */
-
 
 package com.sun.org.apache.xalan.internal.xsltc.trax;
 
 import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;
 import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
-import java.util.Vector;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.xml.sax.ContentHandler;
@@ -58,7 +54,7 @@
     private ContentHandler _sax = null;
     private LexicalHandler _lex = null;
     private SAXImpl _saxImpl = null;
-    private Map<String, Stack> _nsPrefixes = new HashMap<>();
+    private Map<String, Stack<String>> _nsPrefixes = new HashMap<>();
 
     public DOM2SAX(Node root) {
         _dom = root;
@@ -73,7 +69,7 @@
     {
         _sax = handler;
         if (handler instanceof LexicalHandler) {
-            _lex = (LexicalHandler) handler;
+            _lex = (LexicalHandler)handler;
         }
 
         if (handler instanceof SAXImpl) {
@@ -90,25 +86,22 @@
         throws SAXException
     {
         boolean pushed = true;
-        Stack uriStack = _nsPrefixes.get(prefix);
+        Stack<String> uriStack = _nsPrefixes.get(prefix);
 
         if (uriStack != null) {
             if (uriStack.isEmpty()) {
                 _sax.startPrefixMapping(prefix, uri);
                 uriStack.push(uri);
-            }
-            else {
-                final String lastUri = (String) uriStack.peek();
+            } else {
+                final String lastUri = uriStack.peek();
                 if (!lastUri.equals(uri)) {
                     _sax.startPrefixMapping(prefix, uri);
                     uriStack.push(uri);
-                }
-                else {
+                } else {
                     pushed = false;
                 }
             }
-        }
-        else {
+        } else {
             _sax.startPrefixMapping(prefix, uri);
             _nsPrefixes.put(prefix, uriStack = new Stack());
             uriStack.push(uri);
@@ -123,7 +116,7 @@
     private void endPrefixMapping(String prefix)
         throws SAXException
     {
-        final Stack uriStack = _nsPrefixes.get(prefix);
+        final Stack<String> uriStack = _nsPrefixes.get(prefix);
 
         if (uriStack != null) {
             _sax.endPrefixMapping(prefix);
@@ -131,22 +124,6 @@
         }
     }
 
-    /**
-     * If the DOM was created using a DOM 1.0 API, the local name may be
-     * null. If so, get the local name from the qualified name before
-     * generating the SAX event.
-     */
-    private static String getLocalName(Node node) {
-        final String localName = node.getLocalName();
-
-        if (localName == null) {
-            final String qname = node.getNodeName();
-            final int col = qname.lastIndexOf(':');
-            return (col > 0) ? qname.substring(col + 1) : qname;
-        }
-        return localName;
-    }
-
     public void parse(InputSource unused) throws IOException, SAXException {
         parse(_dom);
     }
@@ -173,8 +150,8 @@
      * declarations.
      */
     private void parse(Node node) throws IOException, SAXException {
-        Node first = null;
-        if (node == null) return;
+        if (node == null)
+            return;
 
         switch (node.getNodeType()) {
         case Node.ATTRIBUTE_NODE:         // handled by ELEMENT_NODE
@@ -198,7 +175,6 @@
                 _sax.characters(cdata.toCharArray(), 0, cdata.length());
             }
             break;
-
         case Node.COMMENT_NODE:           // should be handled!!!
             if (_lex != null) {
                 final String value = node.getNodeValue();
@@ -216,10 +192,9 @@
             }
             _sax.endDocument();
             break;
-
         case Node.ELEMENT_NODE:
             String prefix;
-            Vector pushedPrefixes = new Vector();
+            ArrayList<String> pushedPrefixes = new ArrayList<>();
             final AttributesImpl attrs = new AttributesImpl();
             final NamedNodeMap map = node.getAttributes();
             final int length = map.getLength();
@@ -235,7 +210,7 @@
                     final int colon = qnameAttr.lastIndexOf(':');
                     prefix = (colon > 0) ? qnameAttr.substring(colon + 1) : EMPTYSTRING;
                     if (startPrefixMapping(prefix, uriAttr)) {
-                        pushedPrefixes.addElement(prefix);
+                        pushedPrefixes.add(prefix);
                     }
                 }
             }
@@ -248,27 +223,25 @@
                 // Ignore NS declarations here
                 if (!qnameAttr.startsWith(XMLNS_PREFIX)) {
                     final String uriAttr = attr.getNamespaceURI();
-                    final String localNameAttr = getLocalName(attr);
 
                     // Uri may be implicitly declared
                     if (uriAttr != null) {
                         final int colon = qnameAttr.lastIndexOf(':');
                         if (colon > 0) {
                             prefix = qnameAttr.substring(0, colon);
-                        }
-                        else {
+                        } else {
                             // If no prefix for this attr, we need to create
                             // one because we cannot use the default ns
                             prefix = BasisLibrary.generatePrefix();
                             qnameAttr = prefix + ':' + qnameAttr;
                         }
                         if (startPrefixMapping(prefix, uriAttr)) {
-                            pushedPrefixes.addElement(prefix);
+                            pushedPrefixes.add(prefix);
                         }
                     }
 
                     // Add attribute to list
-                    attrs.addAttribute(attr.getNamespaceURI(), getLocalName(attr),
+                    attrs.addAttribute(attr.getNamespaceURI(), attr.getLocalName(),
                         qnameAttr, "CDATA", attr.getNodeValue());
                 }
             }
@@ -276,22 +249,21 @@
             // Now process the element itself
             final String qname = node.getNodeName();
             final String uri = node.getNamespaceURI();
-            final String localName = getLocalName(node);
+            final String localName = node.getLocalName();
 
-            // Uri may be implicitly declared
+            // URI may be implicitly declared
             if (uri != null) {
                 final int colon = qname.lastIndexOf(':');
                 prefix = (colon > 0) ? qname.substring(0, colon) : EMPTYSTRING;
                 if (startPrefixMapping(prefix, uri)) {
-                    pushedPrefixes.addElement(prefix);
+                    pushedPrefixes.add(prefix);
                 }
             }
 
             // Generate SAX event to start element
             if (_saxImpl != null) {
                 _saxImpl.startElement(uri, localName, qname, attrs, node);
-            }
-            else {
+            } else {
                 _sax.startElement(uri, localName, qname, attrs);
             }
 
@@ -308,15 +280,13 @@
             // Generate endPrefixMapping() for all pushed prefixes
             final int nPushedPrefixes = pushedPrefixes.size();
             for (int i = 0; i < nPushedPrefixes; i++) {
-                endPrefixMapping((String) pushedPrefixes.elementAt(i));
+                endPrefixMapping(pushedPrefixes.get(i));
             }
             break;
-
         case Node.PROCESSING_INSTRUCTION_NODE:
             _sax.processingInstruction(node.getNodeName(),
                                        node.getNodeValue());
             break;
-
         case Node.TEXT_NODE:
             final String data = node.getNodeValue();
             _sax.characters(data.toCharArray(), 0, data.length());
@@ -449,36 +419,4 @@
     public String getSystemId() {
         return null;
     }
-
-    // Debugging
-    private String getNodeTypeFromCode(short code) {
-        String retval = null;
-        switch (code) {
-        case Node.ATTRIBUTE_NODE :
-            retval = "ATTRIBUTE_NODE"; break;
-        case Node.CDATA_SECTION_NODE :
-            retval = "CDATA_SECTION_NODE"; break;
-        case Node.COMMENT_NODE :
-            retval = "COMMENT_NODE"; break;
-        case Node.DOCUMENT_FRAGMENT_NODE :
-            retval = "DOCUMENT_FRAGMENT_NODE"; break;
-        case Node.DOCUMENT_NODE :
-            retval = "DOCUMENT_NODE"; break;
-        case Node.DOCUMENT_TYPE_NODE :
-            retval = "DOCUMENT_TYPE_NODE"; break;
-        case Node.ELEMENT_NODE :
-            retval = "ELEMENT_NODE"; break;
-        case Node.ENTITY_NODE :
-            retval = "ENTITY_NODE"; break;
-        case Node.ENTITY_REFERENCE_NODE :
-            retval = "ENTITY_REFERENCE_NODE"; break;
-        case Node.NOTATION_NODE :
-            retval = "NOTATION_NODE"; break;
-        case Node.PROCESSING_INSTRUCTION_NODE :
-            retval = "PROCESSING_INSTRUCTION_NODE"; break;
-        case Node.TEXT_NODE:
-            retval = "TEXT_NODE"; break;
-        }
-        return retval;
-    }
 }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -17,14 +17,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/*
- * $Id: SAX2DTM.java,v 1.2.4.1 2005/09/15 08:15:11 suresh_emailid Exp $
- */
+
 package com.sun.org.apache.xml.internal.dtm.ref.sax2dtm;
 
-
-import com.sun.org.apache.xml.internal.dtm.*;
-import com.sun.org.apache.xml.internal.dtm.ref.*;
+import com.sun.org.apache.xml.internal.dtm.DTM;
+import com.sun.org.apache.xml.internal.dtm.DTMManager;
+import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
+import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators;
+import com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault;
+import com.sun.org.apache.xml.internal.dtm.ref.DTMStringPool;
+import com.sun.org.apache.xml.internal.dtm.ref.DTMTreeWalker;
+import com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource;
+import com.sun.org.apache.xml.internal.dtm.ref.NodeLocator;
 import com.sun.org.apache.xml.internal.res.XMLErrorResources;
 import com.sun.org.apache.xml.internal.res.XMLMessages;
 import com.sun.org.apache.xml.internal.utils.FastStringBuffer;
@@ -36,13 +40,23 @@
 import com.sun.org.apache.xml.internal.utils.WrappedRuntimeException;
 import com.sun.org.apache.xml.internal.utils.XMLString;
 import com.sun.org.apache.xml.internal.utils.XMLStringFactory;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Vector;
 import javax.xml.transform.Source;
 import javax.xml.transform.SourceLocator;
-import org.xml.sax.*;
-import org.xml.sax.ext.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.DeclHandler;
+import org.xml.sax.ext.LexicalHandler;
 
 /**
  * This class implements a DTM that tends to be optimized more for speed than
@@ -82,7 +96,6 @@
    *
    * Made protected rather than private so SAX2RTFDTM can access it.
    */
-  //private FastStringBuffer m_chars = new FastStringBuffer(13, 13);
   protected FastStringBuffer m_chars;
 
   /** This vector holds offset and length data.
@@ -102,8 +115,7 @@
   /** Namespace support, only relevent at construction time.
    * Made protected rather than private so SAX2RTFDTM can access it.
    */
-  transient protected java.util.Vector m_prefixMappings =
-    new java.util.Vector();
+  transient protected Vector<String> m_prefixMappings = new Vector<>();
 
   /** Namespace support, only relevent at construction time.
    * Made protected rather than private so SAX2RTFDTM can access it.
@@ -164,7 +176,7 @@
    * Vector of entities.  Each record is composed of four Strings:
    *  publicId, systemID, notationName, and name.
    */
-  private Vector m_entities = null;
+  private ArrayList<String> m_entities = null;
 
   /** m_entities public ID offset. */
   private static final int ENTITY_FIELD_PUBLICID = 0;
@@ -196,13 +208,15 @@
    */
   protected boolean m_useSourceLocationProperty = false;
 
-   /** Made protected for access by SAX2RTFDTM.
+  /** Made protected for access by SAX2RTFDTM.
    */
   protected StringVector m_sourceSystemId;
-   /** Made protected for access by SAX2RTFDTM.
+
+  /** Made protected for access by SAX2RTFDTM.
    */
   protected IntVector m_sourceLine;
-   /** Made protected for access by SAX2RTFDTM.
+
+  /** Made protected for access by SAX2RTFDTM.
    */
   protected IntVector m_sourceColumn;
 
@@ -252,23 +266,19 @@
                  boolean usePrevsib,
                  boolean newNameTable)
   {
-
     super(mgr, source, dtmIdentity, whiteSpaceFilter,
           xstringfactory, doIndexing, blocksize, usePrevsib, newNameTable);
 
     // %OPT% Use smaller sizes for all internal storage units when
     // the blocksize is small. This reduces the cost of creating an RTF.
-    if (blocksize <= 64)
-    {
+    if (blocksize <= 64) {
       m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
       m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS_SMALL);
       m_valuesOrPrefixes = new DTMStringPool(16);
       m_chars = new FastStringBuffer(7, 10);
       m_contextIndexes = new IntStack(4);
       m_parents = new IntStack(4);
-    }
-    else
-    {
+    } else {
       m_data = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
       m_dataOrQName = new SuballocatedIntVector(blocksize, DEFAULT_NUMBLOCKS);
       m_valuesOrPrefixes = new DTMStringPool();
@@ -289,7 +299,7 @@
     // m_useSourceLocationProperty=com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.m_source_location;
     m_useSourceLocationProperty = mgr.getSource_location();
     m_sourceSystemId = (m_useSourceLocationProperty) ? new StringVector() : null;
-        m_sourceLine = (m_useSourceLocationProperty) ?  new IntVector() : null;
+    m_sourceLine = (m_useSourceLocationProperty) ?  new IntVector() : null;
     m_sourceColumn = (m_useSourceLocationProperty) ?  new IntVector() : null;
   }
 
@@ -297,8 +307,7 @@
    * Set whether information about document source location
    * should be maintained or not.
    */
-  public void setUseSourceLocation(boolean useSourceLocation)
-  {
+  public void setUseSourceLocation(boolean useSourceLocation) {
     m_useSourceLocationProperty = useSourceLocation;
   }
 
@@ -309,17 +318,14 @@
    *
    * @return The data or qualified name, or DTM.NULL.
    */
-  protected int _dataOrQName(int identity)
-  {
-
+  protected int _dataOrQName(int identity) {
     if (identity < m_size)
       return m_dataOrQName.elementAt(identity);
 
     // Check to see if the information requested has been processed, and,
     // if not, advance the iterator until we the information has been
     // processed.
-    while (true)
-    {
+    while (true) {
       boolean isMore = nextNode();
 
       if (!isMore)
@@ -332,8 +338,7 @@
   /**
    * Ask the CoRoutine parser to doTerminate and clear the reference.
    */
-  public void clearCoRoutine()
-  {
+  public void clearCoRoutine() {
     clearCoRoutine(true);
   }
 
@@ -344,11 +349,8 @@
    * @param callDoTerminate true of doTerminate should be called on the
    * coRoutine parser.
    */
-  public void clearCoRoutine(boolean callDoTerminate)
-  {
-
-    if (null != m_incrementalSAXSource)
-    {
+  public void clearCoRoutine(boolean callDoTerminate) {
+    if (null != m_incrementalSAXSource) {
       if (callDoTerminate)
         m_incrementalSAXSource.deliverMoreNodes(false);
 
@@ -368,9 +370,7 @@
    * @param incrementalSAXSource The parser that we want to recieve events from
    * on demand.
    */
-  public void setIncrementalSAXSource(IncrementalSAXSource incrementalSAXSource)
-  {
-
+  public void setIncrementalSAXSource(IncrementalSAXSource incrementalSAXSource) {
     // Establish coroutine link so we can request more data
     //
     // Note: It's possible that some versions of IncrementalSAXSource may
@@ -406,11 +406,9 @@
    * Note that IncrementalSAXSource_Filter is package private, hence
    * it can be statically referenced using instanceof (CR 6537912).
    */
-  public ContentHandler getContentHandler()
-  {
-
-    if (m_incrementalSAXSource.getClass()
-        .getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
+  public ContentHandler getContentHandler() {
+    if (m_incrementalSAXSource.getClass().getName()
+        .equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
       return (ContentHandler) m_incrementalSAXSource;
     else
       return this;
@@ -429,11 +427,9 @@
    * Note that IncrementalSAXSource_Filter is package private, hence
    * it can be statically referenced using instanceof (CR 6537912).
    */
-  public LexicalHandler getLexicalHandler()
-  {
-
-    if (m_incrementalSAXSource.getClass()
-        .getName().equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
+  public LexicalHandler getLexicalHandler() {
+    if (m_incrementalSAXSource.getClass().getName()
+        .equals("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter"))
       return (LexicalHandler) m_incrementalSAXSource;
     else
       return this;
@@ -444,8 +440,7 @@
    *
    * @return null if this model doesn't respond to SAX entity ref events.
    */
-  public EntityResolver getEntityResolver()
-  {
+  public EntityResolver getEntityResolver() {
     return this;
   }
 
@@ -454,8 +449,7 @@
    *
    * @return null if this model doesn't respond to SAX dtd events.
    */
-  public DTDHandler getDTDHandler()
-  {
+  public DTDHandler getDTDHandler() {
     return this;
   }
 
@@ -464,8 +458,7 @@
    *
    * @return null if this model doesn't respond to SAX error events.
    */
-  public ErrorHandler getErrorHandler()
-  {
+  public ErrorHandler getErrorHandler() {
     return this;
   }
 
@@ -474,8 +467,7 @@
    *
    * @return null if this model doesn't respond to SAX Decl events.
    */
-  public DeclHandler getDeclHandler()
-  {
+  public DeclHandler getDeclHandler() {
     return this;
   }
 
@@ -485,8 +477,7 @@
    * transformation and the parse run simultaneously. Guidance to the
    * DTMManager.
    */
-  public boolean needsTwoThreads()
-  {
+  public boolean needsTwoThreads() {
     return null != m_incrementalSAXSource;
   }
 
@@ -509,9 +500,8 @@
    */
   public void dispatchCharactersEvents(int nodeHandle, ContentHandler ch,
                                        boolean normalize)
-          throws SAXException
+    throws SAXException
   {
-
     int identity = makeNodeIdentity(nodeHandle);
 
     if (identity == DTM.NULL)
@@ -519,8 +509,7 @@
 
     int type = _type(identity);
 
-    if (isTextType(type))
-    {
+    if (isTextType(type)) {
       int dataIndex = m_dataOrQName.elementAt(identity);
       int offset = m_data.elementAt(dataIndex);
       int length = m_data.elementAt(dataIndex + 1);
@@ -529,13 +518,10 @@
         m_chars.sendNormalizedSAXcharacters(ch, offset, length);
       else
         m_chars.sendSAXcharacters(ch, offset, length);
-    }
-    else
-    {
+    } else {
       int firstChild = _firstch(identity);
 
-      if (DTM.NULL != firstChild)
-      {
+      if (DTM.NULL != firstChild) {
         int offset = -1;
         int length = 0;
         int startNode = identity;
@@ -545,12 +531,10 @@
         do {
           type = _type(identity);
 
-          if (isTextType(type))
-          {
+          if (isTextType(type)) {
             int dataIndex = _dataOrQName(identity);
 
-            if (-1 == offset)
-            {
+            if (-1 == offset) {
               offset = m_data.elementAt(dataIndex);
             }
 
@@ -560,36 +544,31 @@
           identity = getNextNodeIdentity(identity);
         } while (DTM.NULL != identity && (_parent(identity) >= startNode));
 
-        if (length > 0)
-        {
+        if (length > 0) {
           if(normalize)
             m_chars.sendNormalizedSAXcharacters(ch, offset, length);
           else
             m_chars.sendSAXcharacters(ch, offset, length);
         }
-      }
-      else if(type != DTM.ELEMENT_NODE)
-      {
+      } else if(type != DTM.ELEMENT_NODE) {
         int dataIndex = _dataOrQName(identity);
 
-        if (dataIndex < 0)
-        {
+        if (dataIndex < 0) {
           dataIndex = -dataIndex;
           dataIndex = m_data.elementAt(dataIndex + 1);
         }
 
         String str = m_valuesOrPrefixes.indexToString(dataIndex);
 
-          if(normalize)
-            FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
-                                                         0, str.length(), ch);
-          else
-            ch.characters(str.toCharArray(), 0, str.length());
+        if(normalize)
+          FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
+                                                       0, str.length(), ch);
+        else
+          ch.characters(str.toCharArray(), 0, str.length());
       }
     }
   }
 
-
   /**
    * Given a node handle, return its DOM-style node name. This will
    * include names such as #text or #document.
@@ -599,39 +578,29 @@
    * %REVIEW% Document when empty string is possible...
    * %REVIEW-COMMENT% It should never be empty, should it?
    */
-  public String getNodeName(int nodeHandle)
-  {
-
+  public String getNodeName(int nodeHandle) {
     int expandedTypeID = getExpandedTypeID(nodeHandle);
     // If just testing nonzero, no need to shift...
     int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
 
-    if (0 == namespaceID)
-    {
+    if (0 == namespaceID) {
       // Don't retrieve name until/unless needed
       // String name = m_expandedNameTable.getLocalName(expandedTypeID);
       int type = getNodeType(nodeHandle);
 
-      if (type == DTM.NAMESPACE_NODE)
-      {
+      if (type == DTM.NAMESPACE_NODE) {
         if (null == m_expandedNameTable.getLocalName(expandedTypeID))
           return "xmlns";
         else
           return "xmlns:" + m_expandedNameTable.getLocalName(expandedTypeID);
-      }
-      else if (0 == m_expandedNameTable.getLocalNameID(expandedTypeID))
-      {
+      } else if (0 == m_expandedNameTable.getLocalNameID(expandedTypeID)) {
         return m_fixednames[type];
-      }
-      else
+      } else
         return m_expandedNameTable.getLocalName(expandedTypeID);
-    }
-    else
-    {
+    } else {
       int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
 
-      if (qnameIndex < 0)
-      {
+      if (qnameIndex < 0) {
         qnameIndex = -qnameIndex;
         qnameIndex = m_data.elementAt(qnameIndex);
       }
@@ -648,27 +617,21 @@
    * @param nodeHandle the id of the node.
    * @return String Name of this node, which may be an empty string.
    */
-  public String getNodeNameX(int nodeHandle)
-  {
-
+  public String getNodeNameX(int nodeHandle) {
     int expandedTypeID = getExpandedTypeID(nodeHandle);
     int namespaceID = m_expandedNameTable.getNamespaceID(expandedTypeID);
 
-    if (0 == namespaceID)
-    {
+    if (namespaceID == 0) {
       String name = m_expandedNameTable.getLocalName(expandedTypeID);
 
       if (name == null)
         return "";
       else
         return name;
-    }
-    else
-    {
+    } else {
       int qnameIndex = m_dataOrQName.elementAt(makeNodeIdentity(nodeHandle));
 
-      if (qnameIndex < 0)
-      {
+      if (qnameIndex < 0) {
         qnameIndex = -qnameIndex;
         qnameIndex = m_data.elementAt(qnameIndex);
       }
@@ -686,11 +649,9 @@
    * @return <code>true</code> if the attribute was specified;
    *         <code>false</code> if it was defaulted.
    */
-  public boolean isAttributeSpecified(int attributeHandle)
-  {
-
+  public boolean isAttributeSpecified(int attributeHandle) {
     // I'm not sure if I want to do anything with this...
-    return true;  // ??
+    return true; // ??
   }
 
   /**
@@ -701,9 +662,7 @@
    *
    * @return the system identifier String object, or null if there is none.
    */
-  public String getDocumentTypeDeclarationSystemIdentifier()
-  {
-
+  public String getDocumentTypeDeclarationSystemIdentifier() {
     /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMDefaultBase abstract method */
     error(XMLMessages.createXMLMessage(XMLErrorResources.ER_METHOD_NOT_SUPPORTED, null));//"Not yet supported!");
 
@@ -717,14 +676,11 @@
    * @param identity The node identity (index).
    * @return identity+1, or DTM.NULL.
    */
-  protected int getNextNodeIdentity(int identity)
-  {
-
+  protected int getNextNodeIdentity(int identity) {
     identity += 1;
 
-    while (identity >= m_size)
-    {
-      if (null == m_incrementalSAXSource)
+    while (identity >= m_size) {
+      if (m_incrementalSAXSource == null)
         return DTM.NULL;
 
       nextNode();
@@ -739,10 +695,10 @@
    * @param nodeHandle The node ID.
    * @param ch A non-null reference to a ContentHandler.
    *
-   * @throws org.xml.sax.SAXException
+   * @throws SAXException
    */
-  public void dispatchToEvents(int nodeHandle, org.xml.sax.ContentHandler ch)
-          throws org.xml.sax.SAXException
+  public void dispatchToEvents(int nodeHandle, ContentHandler ch)
+          throws SAXException
   {
 
     DTMTreeWalker treeWalker = m_walker;
@@ -1087,28 +1043,22 @@
    * @return String containing the URI of the Unparsed Entity, or an
    * empty string if no such entity exists.
    */
-  public String getUnparsedEntityURI(String name)
-  {
-
+  public String getUnparsedEntityURI(String name) {
     String url = "";
 
-    if (null == m_entities)
+    if (null == m_entities) {
       return url;
+    }
 
     int n = m_entities.size();
 
-    for (int i = 0; i < n; i += ENTITY_FIELDS_PER)
-    {
-      String ename = (String) m_entities.elementAt(i + ENTITY_FIELD_NAME);
+    for (int i = 0; i < n; i += ENTITY_FIELDS_PER) {
+      String ename = m_entities.get(i + ENTITY_FIELD_NAME);
 
-      if (null != ename && ename.equals(name))
-      {
-        String nname = (String) m_entities.elementAt(i
-                         + ENTITY_FIELD_NOTATIONNAME);
+      if (null != ename && ename.equals(name)) {
+        String nname = m_entities.get(i + ENTITY_FIELD_NOTATIONNAME);
 
-        if (null != nname)
-        {
-
+        if (null != nname) {
           // The draft says: "The XSLT processor may use the public
           // identifier to generate a URI for the entity instead of the URI
           // specified in the system identifier. If the XSLT processor does
@@ -1118,11 +1068,10 @@
           // the resource containing the entity declaration as the base
           // URI [RFC2396]."
           // So I'm falling a bit short here.
-          url = (String) m_entities.elementAt(i + ENTITY_FIELD_SYSTEMID);
+          url = m_entities.get(i + ENTITY_FIELD_SYSTEMID);
 
-          if (null == url)
-          {
-            url = (String) m_entities.elementAt(i + ENTITY_FIELD_PUBLICID);
+          if (null == url) {
+            url = m_entities.get(i + ENTITY_FIELD_PUBLICID);
           }
         }
 
@@ -1400,26 +1349,18 @@
    *
    * @return The prefix if there is one, or null.
    */
-  public String getPrefix(String qname, String uri)
-  {
-
+  public String getPrefix(String qname, String uri) {
     String prefix;
     int uriIndex = -1;
 
-    if (null != uri && uri.length() > 0)
-    {
-
-      do
-      {
+    if (null != uri && uri.length() > 0) {
+      do {
         uriIndex = m_prefixMappings.indexOf(uri, ++uriIndex);
-      } while ( (uriIndex & 0x01) == 0);
+      } while ((uriIndex & 0x01) == 0);
 
-      if (uriIndex >= 0)
-      {
-        prefix = (String) m_prefixMappings.elementAt(uriIndex - 1);
-      }
-      else if (null != qname)
-      {
+      if (uriIndex >= 0) {
+        prefix = m_prefixMappings.elementAt(uriIndex - 1);
+      } else if (null != qname) {
         int indexOfNSSep = qname.indexOf(':');
 
         if (qname.equals("xmlns"))
@@ -1429,33 +1370,24 @@
         else
           prefix = (indexOfNSSep > 0)
                    ? qname.substring(0, indexOfNSSep) : null;
-      }
-      else
-      {
+      } else {
         prefix = null;
       }
-    }
-    else if (null != qname)
-    {
+    } else if (null != qname) {
       int indexOfNSSep = qname.indexOf(':');
 
-      if (indexOfNSSep > 0)
-      {
+      if (indexOfNSSep > 0) {
         if (qname.startsWith("xmlns:"))
           prefix = qname.substring(indexOfNSSep + 1);
         else
           prefix = qname.substring(0, indexOfNSSep);
-      }
-      else
-      {
+      } else {
         if (qname.equals("xmlns"))
           prefix = "";
         else
           prefix = null;
       }
-    }
-    else
-    {
+    } else {
       prefix = null;
     }
 
@@ -1470,38 +1402,31 @@
    *
    * @return The prefix if there is one, or null.
    */
-  public int getIdForNamespace(String uri)
-  {
-
+  public int getIdForNamespace(String uri) {
      return m_valuesOrPrefixes.stringToIndex(uri);
-
   }
 
-    /**
+  /**
    * Get a prefix either from the qname or from the uri mapping, or just make
    * one up!
    *
    * @return The prefix if there is one, or null.
    */
-  public String getNamespaceURI(String prefix)
-  {
-
+  public String getNamespaceURI(String prefix) {
     String uri = "";
     int prefixIndex = m_contextIndexes.peek() - 1 ;
 
-    if(null == prefix)
+    if (null == prefix) {
       prefix = "";
+    }
 
-      do
-      {
-        prefixIndex = m_prefixMappings.indexOf(prefix, ++prefixIndex);
-      } while ( (prefixIndex >= 0) && (prefixIndex & 0x01) == 0x01);
+    do {
+      prefixIndex = m_prefixMappings.indexOf(prefix, ++prefixIndex);
+    } while ((prefixIndex >= 0) && (prefixIndex & 0x01) == 0x01);
 
-      if (prefixIndex > -1)
-      {
-        uri = (String) m_prefixMappings.elementAt(prefixIndex + 1);
-      }
-
+    if (prefixIndex > -1) {
+      uri = m_prefixMappings.elementAt(prefixIndex + 1);
+    }
 
     return uri;
   }
@@ -1578,7 +1503,7 @@
    *         default behaviour.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.EntityResolver#resolveEntity
+   * @see EntityResolver#resolveEntity
    *
    * @throws SAXException
    */
@@ -1605,7 +1530,7 @@
    * @param systemId The notation system identifier.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.DTDHandler#notationDecl
+   * @see DTDHandler#notationDecl
    *
    * @throws SAXException
    */
@@ -1630,41 +1555,35 @@
    * @param notationName The name of the associated notation.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+   * @see DTDHandler#unparsedEntityDecl
    *
    * @throws SAXException
    */
-  public void unparsedEntityDecl(
-          String name, String publicId, String systemId, String notationName)
-            throws SAXException
+  public void unparsedEntityDecl(String name, String publicId, String systemId,
+                                 String notationName) throws SAXException
   {
-
-    if (null == m_entities)
-    {
-      m_entities = new Vector();
+    if (null == m_entities) {
+      m_entities = new ArrayList<>();
     }
 
-    try
-    {
+    try {
       systemId = SystemIDResolver.getAbsoluteURI(systemId,
                                                  getDocumentBaseURI());
-    }
-    catch (Exception e)
-    {
-      throw new org.xml.sax.SAXException(e);
+    } catch (Exception e) {
+      throw new SAXException(e);
     }
 
     //  private static final int ENTITY_FIELD_PUBLICID = 0;
-    m_entities.addElement(publicId);
+    m_entities.add(publicId);
 
     //  private static final int ENTITY_FIELD_SYSTEMID = 1;
-    m_entities.addElement(systemId);
+    m_entities.add(systemId);
 
     //  private static final int ENTITY_FIELD_NOTATIONNAME = 2;
-    m_entities.addElement(notationName);
+    m_entities.add(notationName);
 
     //  private static final int ENTITY_FIELD_NAME = 3;
-    m_entities.addElement(name);
+    m_entities.add(name);
   }
 
   ////////////////////////////////////////////////////////////////////
@@ -1679,8 +1598,8 @@
    * with other document events.</p>
    *
    * @param locator A locator for all SAX document events.
-   * @see org.xml.sax.ContentHandler#setDocumentLocator
-   * @see org.xml.sax.Locator
+   * @see ContentHandler#setDocumentLocator
+   * @see Locator
    */
   public void setDocumentLocator(Locator locator)
   {
@@ -1693,7 +1612,7 @@
    *
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#startDocument
+   * @see ContentHandler#startDocument
    */
   public void startDocument() throws SAXException
   {
@@ -1716,7 +1635,7 @@
    *
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#endDocument
+   * @see ContentHandler#endDocument
    */
   public void endDocument() throws SAXException
   {
@@ -1754,7 +1673,7 @@
    * @param uri The Namespace URI mapped to the prefix.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#startPrefixMapping
+   * @see ContentHandler#startPrefixMapping
    */
   public void startPrefixMapping(String prefix, String uri)
           throws SAXException
@@ -1780,7 +1699,7 @@
    * @param prefix The Namespace prefix being declared.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#endPrefixMapping
+   * @see ContentHandler#endPrefixMapping
    */
   public void endPrefixMapping(String prefix) throws SAXException
   {
@@ -1815,16 +1734,13 @@
    * @return true if the declaration has already been declared in the
    *         current context.
    */
-  protected boolean declAlreadyDeclared(String prefix)
-  {
-
+  protected boolean declAlreadyDeclared(String prefix) {
     int startDecls = m_contextIndexes.peek();
-    java.util.Vector prefixMappings = m_prefixMappings;
+    Vector<String> prefixMappings = m_prefixMappings;
     int nDecls = prefixMappings.size();
 
-    for (int i = startDecls; i < nDecls; i += 2)
-    {
-      String prefixDecl = (String) prefixMappings.elementAt(i);
+    for (int i = startDecls; i < nDecls; i += 2) {
+      String prefixDecl = prefixMappings.elementAt(i);
 
       if (prefixDecl == null)
         continue;
@@ -1836,7 +1752,7 @@
     return false;
   }
 
-        boolean m_pastFirstElement=false;
+  boolean m_pastFirstElement=false;
 
   /**
    * Receive notification of the start of an element.
@@ -1857,35 +1773,38 @@
    * @param attributes The specified or defaulted attributes.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#startElement
+   * @see ContentHandler#startElement
    */
-  public void startElement(
-          String uri, String localName, String qName, Attributes attributes)
-            throws SAXException
+  public void startElement(String uri, String localName, String qName,
+                           Attributes attributes) throws SAXException
   {
-   if (DEBUG)
-         {
-      System.out.println("startElement: uri: " + uri + ", localname: "
-                                                                                                 + localName + ", qname: "+qName+", atts: " + attributes);
+    if (DEBUG) {
+      System.out.println("startElement: uri: " + uri +
+                         ", localname: " + localName +
+                         ", qname: "+qName+", atts: " + attributes);
 
-                        boolean DEBUG_ATTRS=true;
-                        if(DEBUG_ATTRS & attributes!=null)
-                        {
-                                int n = attributes.getLength();
-                                if(n==0)
-                                        System.out.println("\tempty attribute list");
-                                else for (int i = 0; i < n; i++)
-                                        System.out.println("\t attr: uri: " + attributes.getURI(i) +
-                                                                                                                 ", localname: " + attributes.getLocalName(i) +
-                                                                                                                 ", qname: " + attributes.getQName(i) +
-                                                                                                                 ", type: " + attributes.getType(i) +
-                                                                                                                 ", value: " + attributes.getValue(i)
-                                                                                                                 );
-                        }
-         }
+      boolean DEBUG_ATTRS=true;
+      if (DEBUG_ATTRS & attributes!=null) {
+        int n = attributes.getLength();
+        if (n==0) {
+          System.out.println("\tempty attribute list");
+        } else for (int i = 0; i < n; i++) {
+          System.out.println("\t attr: uri: " + attributes.getURI(i) +
+                             ", localname: " + attributes.getLocalName(i) +
+                             ", qname: " + attributes.getQName(i) +
+                             ", type: " + attributes.getType(i) +
+                             ", value: " + attributes.getValue(i));
+        }
+      }
+    }
 
     charactersFlush();
 
+    if ((localName == null || localName.isEmpty()) &&
+        (uri == null || uri.isEmpty())) {
+      localName = qName;
+    }
+
     int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
     String prefix = getPrefix(qName, uri);
     int prefixIndex = (null != prefix)
@@ -1894,20 +1813,18 @@
     int elemNode = addNode(DTM.ELEMENT_NODE, exName,
                            m_parents.peek(), m_previous, prefixIndex, true);
 
-    if(m_indexing)
+    if (m_indexing)
       indexNode(exName, elemNode);
 
-
     m_parents.push(elemNode);
 
     int startDecls = m_contextIndexes.peek();
     int nDecls = m_prefixMappings.size();
     int prev = DTM.NULL;
 
-    if(!m_pastFirstElement)
-    {
+    if (!m_pastFirstElement) {
       // SPECIAL CASE: Implied declaration at root element
-      prefix="xml";
+      prefix = "xml";
       String declURL = "http://www.w3.org/XML/1998/namespace";
       exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
       int val = m_valuesOrPrefixes.stringToIndex(declURL);
@@ -1916,14 +1833,13 @@
       m_pastFirstElement=true;
     }
 
-    for (int i = startDecls; i < nDecls; i += 2)
-    {
-      prefix = (String) m_prefixMappings.elementAt(i);
+    for (int i = startDecls; i < nDecls; i += 2) {
+      prefix = m_prefixMappings.elementAt(i);
 
       if (prefix == null)
         continue;
 
-      String declURL = (String) m_prefixMappings.elementAt(i + 1);
+      String declURL = m_prefixMappings.elementAt(i + 1);
 
       exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
 
@@ -1935,8 +1851,7 @@
 
     int n = attributes.getLength();
 
-    for (int i = 0; i < n; i++)
-    {
+    for (int i = 0; i < n; i++) {
       String attrUri = attributes.getURI(i);
       String attrQName = attributes.getQName(i);
       String valString = attributes.getValue(i);
@@ -1947,17 +1862,13 @@
 
        String attrLocalName = attributes.getLocalName(i);
 
-      if ((null != attrQName)
-              && (attrQName.equals("xmlns")
-                  || attrQName.startsWith("xmlns:")))
-      {
+      if ((null != attrQName) &&
+          (attrQName.equals("xmlns") || attrQName.startsWith("xmlns:"))) {
         if (declAlreadyDeclared(prefix))
           continue;  // go to the next attribute.
 
         nodeType = DTM.NAMESPACE_NODE;
-      }
-      else
-      {
+      } else {
         nodeType = DTM.ATTRIBUTE_NODE;
 
         if (attributes.getType(i).equalsIgnoreCase("ID"))
@@ -1966,15 +1877,13 @@
 
       // Bit of a hack... if somehow valString is null, stringToIndex will
       // return -1, which will make things very unhappy.
-      if(null == valString)
+      if (null == valString)
         valString = "";
 
       int val = m_valuesOrPrefixes.stringToIndex(valString);
       //String attrLocalName = attributes.getLocalName(i);
 
-      if (null != prefix)
-      {
-
+      if (null != prefix) {
         prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);
 
         int dataIndex = m_data.size();
@@ -1993,8 +1902,7 @@
     if (DTM.NULL != prev)
       m_nextsib.setElementAt(DTM.NULL,prev);
 
-    if (null != m_wsfilter)
-    {
+    if (null != m_wsfilter) {
       short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
       boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
                             ? getShouldStripWhitespace()
@@ -2026,7 +1934,7 @@
    *        empty string if qualified names are not available.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#endElement
+   * @see ContentHandler#endElement
    */
   public void endElement(String uri, String localName, String qName)
           throws SAXException
@@ -2074,7 +1982,7 @@
    *               character array.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#characters
+   * @see ContentHandler#characters
    */
   public void characters(char ch[], int start, int length) throws SAXException
   {
@@ -2109,7 +2017,7 @@
    *               character array.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#ignorableWhitespace
+   * @see ContentHandler#ignorableWhitespace
    */
   public void ignorableWhitespace(char ch[], int start, int length)
           throws SAXException
@@ -2133,7 +2041,7 @@
    *             none is supplied.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#processingInstruction
+   * @see ContentHandler#processingInstruction
    */
   public void processingInstruction(String target, String data)
           throws SAXException
@@ -2163,7 +2071,7 @@
    * @param name The name of the skipped entity.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#processingInstruction
+   * @see ContentHandler#processingInstruction
    */
   public void skippedEntity(String name) throws SAXException
   {
@@ -2187,8 +2095,8 @@
    * @param e The warning information encoded as an exception.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ErrorHandler#warning
-   * @see org.xml.sax.SAXParseException
+   * @see ErrorHandler#warning
+   * @see SAXParseException
    */
   public void warning(SAXParseException e) throws SAXException
   {
@@ -2208,8 +2116,8 @@
    * @param e The warning information encoded as an exception.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ErrorHandler#warning
-   * @see org.xml.sax.SAXParseException
+   * @see ErrorHandler#warning
+   * @see SAXParseException
    */
   public void error(SAXParseException e) throws SAXException
   {
@@ -2230,8 +2138,8 @@
    * @param e The error information encoded as an exception.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ErrorHandler#fatalError
-   * @see org.xml.sax.SAXParseException
+   * @see ErrorHandler#fatalError
+   * @see SAXParseException
    */
   public void fatalError(SAXParseException e) throws SAXException
   {
@@ -2299,7 +2207,7 @@
    * @param value The replacement text of the entity.
    * @throws SAXException The application may raise an exception.
    * @see #externalEntityDecl
-   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+   * @see DTDHandler#unparsedEntityDecl
    */
   public void internalEntityDecl(String name, String value)
           throws SAXException
@@ -2321,7 +2229,7 @@
    * @param systemId The declared system identifier of the entity.
    * @throws SAXException The application may raise an exception.
    * @see #internalEntityDecl
-   * @see org.xml.sax.DTDHandler#unparsedEntityDecl
+   * @see DTDHandler#unparsedEntityDecl
    */
   public void externalEntityDecl(
           String name, String publicId, String systemId) throws SAXException
@@ -2386,15 +2294,15 @@
    * properly nested within start/end entity events.</p>
    *
    * <p>Note that skipped entities will be reported through the
-   * {@link org.xml.sax.ContentHandler#skippedEntity skippedEntity}
+   * {@link ContentHandler#skippedEntity skippedEntity}
    * event, which is part of the ContentHandler interface.</p>
    *
    * @param name The name of the entity.  If it is a parameter
    *        entity, the name will begin with '%'.
    * @throws SAXException The application may raise an exception.
    * @see #endEntity
-   * @see org.xml.sax.ext.DeclHandler#internalEntityDecl
-   * @see org.xml.sax.ext.DeclHandler#externalEntityDecl
+   * @see DeclHandler#internalEntityDecl
+   * @see DeclHandler#externalEntityDecl
    */
   public void startEntity(String name) throws SAXException
   {
@@ -2419,7 +2327,7 @@
    * Report the start of a CDATA section.
    *
    * <p>The contents of the CDATA section will be reported through
-   * the regular {@link org.xml.sax.ContentHandler#characters
+   * the regular {@link ContentHandler#characters
    * characters} event.</p>
    *
    * @throws SAXException The application may raise an exception.
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,13 +1,13 @@
 /*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * Copyright 1999-2005 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -17,13 +17,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/*
- * $Id: SAX2DTM2.java,v 1.2.4.1 2005/09/15 08:15:12 suresh_emailid Exp $
- */
+
 package com.sun.org.apache.xml.internal.dtm.ref.sax2dtm;
 
-import com.sun.org.apache.xml.internal.dtm.*;
-import com.sun.org.apache.xml.internal.dtm.ref.*;
+import com.sun.org.apache.xml.internal.dtm.DTM;
+import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
+import com.sun.org.apache.xml.internal.dtm.DTMException;
+import com.sun.org.apache.xml.internal.dtm.DTMManager;
+import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;
+import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase;
+import com.sun.org.apache.xml.internal.dtm.ref.ExpandedNameTable;
+import com.sun.org.apache.xml.internal.dtm.ref.ExtendedType;
 import com.sun.org.apache.xml.internal.utils.FastStringBuffer;
 import com.sun.org.apache.xml.internal.utils.XMLString;
 import com.sun.org.apache.xml.internal.utils.XMLStringDefault;
@@ -31,11 +35,12 @@
 import com.sun.org.apache.xml.internal.res.XMLMessages;
 import com.sun.org.apache.xml.internal.res.XMLErrorResources;
 import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
-
+import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector;
+import java.util.ArrayList;
 import javax.xml.transform.Source;
-import java.util.Vector;
-import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector;
-import org.xml.sax.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
 
 /**
  * SAX2DTM2 is an optimized version of SAX2DTM which is used in non-incremental situation.
@@ -53,10 +58,6 @@
  * The design of SAX2DTM2 may limit its extensibilty. If you have a reason to extend the
  * SAX2DTM model, please extend from SAX2DTM instead of this class.
  * <p>
- * TODO: This class is currently only used by XSLTC. We need to investigate the possibility
- * of also using it in Xalan-J Interpretive. Xalan's performance is likely to get an instant
- * boost if we use SAX2DTM2 instead of SAX2DTM in non-incremental case.
- * <p>
  * %MK% The code in this class is critical to the XSLTC_DTM performance. Be very careful
  * when making changes here!
  */
@@ -87,11 +88,10 @@
      */
     public DTMAxisIterator setStartNode(int node)
     {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
-      if (_isRestartable)
-      {
+      if (_isRestartable) {
         _startNode = node;
         _currentNode = (node == DTM.NULL) ? DTM.NULL
                                           : _firstch2(makeNodeIdentity(node));
@@ -108,8 +108,7 @@
      * @return The next node handle in the iteration, or END if no more
      * are available.
      */
-    public int next()
-    {
+    public int next() {
       if (_currentNode != NULL) {
         int node = _currentNode;
         _currentNode = _nextsib2(node);
@@ -139,13 +138,11 @@
      *
      * @return A DTMAxisIterator set to the start of the iteration.
      */
-    public DTMAxisIterator setStartNode(int node)
-    {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+    public DTMAxisIterator setStartNode(int node) {
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
-      if (_isRestartable)
-      {
+      if (_isRestartable) {
         _startNode = node;
 
         if (node != DTM.NULL)
@@ -229,8 +226,7 @@
      *
      * @param nodeType The extended type ID being requested.
      */
-    public TypedChildrenIterator(int nodeType)
-    {
+    public TypedChildrenIterator(int nodeType) {
       _nodeType = nodeType;
     }
 
@@ -242,17 +238,14 @@
      *
      * @return A DTMAxisIterator set to the start of the iteration.
      */
-    public DTMAxisIterator setStartNode(int node)
-    {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+    public DTMAxisIterator setStartNode(int node) {
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
-      if (_isRestartable)
-      {
+      if (_isRestartable) {
         _startNode = node;
-        _currentNode = (node == DTM.NULL)
-                                   ? DTM.NULL
-                                   : _firstch2(makeNodeIdentity(_startNode));
+        _currentNode = (node == DTM.NULL) ? DTM.NULL :
+                         _firstch2(makeNodeIdentity(_startNode));
 
         return resetPosition();
       }
@@ -265,8 +258,7 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
+    public int next() {
       int node = _currentNode;
       if (node == DTM.NULL)
         return DTM.NULL;
@@ -301,14 +293,12 @@
         _currentNode = _nextsib2(node);
         return returnNode(makeNodeHandle(node));
       }
-
     }
 
     /**
      * Return the node at the given position.
      */
-    public int getNodeByPosition(int position)
-    {
+    public int getNodeByPosition(int position) {
       if (position <= 0)
         return DTM.NULL;
 
@@ -327,8 +317,7 @@
           node = _nextsib2(node);
         }
         return NULL;
-      }
-      else {
+      } else {
         while (node != DTM.NULL) {
           if (_exptype2(node) >= DTM.NTYPES) {
             pos++;
@@ -415,13 +404,11 @@
      *
      * @return A DTMAxisIterator set to the start of the iteration.
      */
-    public DTMAxisIterator setStartNode(int node)
-    {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+    public DTMAxisIterator setStartNode(int node) {
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
-      if (_isRestartable)
-      {
+      if (_isRestartable) {
         _startNode = node;
         _currentNode = makeNodeIdentity(node);
 
@@ -436,8 +423,7 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
+    public int next() {
       _currentNode = (_currentNode == DTM.NULL) ? DTM.NULL
                                                 : _nextsib2(_currentNode);
       return returnNode(makeNodeHandle(_currentNode));
@@ -460,8 +446,7 @@
      *
      * @param type The extended type ID being requested.
      */
-    public TypedFollowingSiblingIterator(int type)
-    {
+    public TypedFollowingSiblingIterator(int type) {
       _nodeType = type;
     }
 
@@ -470,8 +455,7 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
+    public int next() {
       if (_currentNode == DTM.NULL) {
         return DTM.NULL;
       }
@@ -481,8 +465,7 @@
 
       if (nodeType != DTM.ELEMENT_NODE) {
         while ((node = _nextsib2(node)) != DTM.NULL && _exptype2(node) != nodeType) {}
-      }
-      else {
+      } else {
         while ((node = _nextsib2(node)) != DTM.NULL && _exptype2(node) < DTM.NTYPES) {}
       }
 
@@ -498,8 +481,7 @@
   /**
    * Iterator that returns attribute nodes (of what nodes?)
    */
-  public final class AttributeIterator extends InternalAxisIteratorBase
-  {
+  public final class AttributeIterator extends InternalAxisIteratorBase {
 
     // assumes caller will pass element nodes
 
@@ -511,13 +493,11 @@
      *
      * @return A DTMAxisIterator set to the start of the iteration.
      */
-    public DTMAxisIterator setStartNode(int node)
-    {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+    public DTMAxisIterator setStartNode(int node) {
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
-      if (_isRestartable)
-      {
+      if (_isRestartable) {
         _startNode = node;
         _currentNode = getFirstAttributeIdentity(makeNodeIdentity(node));
 
@@ -532,9 +512,7 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
-
+    public int next() {
       final int node = _currentNode;
 
       if (node != NULL) {
@@ -561,8 +539,7 @@
      *
      * @param nodeType The extended type ID that is requested.
      */
-    public TypedAttributeIterator(int nodeType)
-    {
+    public TypedAttributeIterator(int nodeType) {
       _nodeType = nodeType;
     }
 
@@ -576,14 +553,10 @@
      *
      * @return A DTMAxisIterator set to the start of the iteration.
      */
-    public DTMAxisIterator setStartNode(int node)
-    {
-      if (_isRestartable)
-      {
+    public DTMAxisIterator setStartNode(int node) {
+      if (_isRestartable) {
         _startNode = node;
-
         _currentNode = getTypedAttribute(node, _nodeType);
-
         return resetPosition();
       }
 
@@ -595,9 +568,7 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
-
+    public int next() {
       final int node = _currentNode;
 
       // singleton iterator, since there can only be one attribute of
@@ -624,8 +595,7 @@
      *
      * @return true.
      */
-    public boolean isReverse()
-    {
+    public boolean isReverse() {
       return true;
     }
 
@@ -637,30 +607,25 @@
      *
      * @return A DTMAxisIterator set to the start of the iteration.
      */
-    public DTMAxisIterator setStartNode(int node)
-    {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+    public DTMAxisIterator setStartNode(int node) {
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
-      if (_isRestartable)
-      {
+      if (_isRestartable) {
         _startNode = node;
         node = _startNodeID = makeNodeIdentity(node);
 
-        if(node == NULL)
-        {
+        if(node == NULL) {
           _currentNode = node;
           return resetPosition();
         }
 
         int type = _type2(node);
-        if(ExpandedNameTable.ATTRIBUTE == type
-           || ExpandedNameTable.NAMESPACE == type )
+        if (ExpandedNameTable.ATTRIBUTE == type ||
+            ExpandedNameTable.NAMESPACE == type)
         {
           _currentNode = node;
-        }
-        else
-        {
+        } else {
           // Be careful to handle the Document node properly
           _currentNode = _parent2(node);
           if(NULL!=_currentNode)
@@ -680,18 +645,12 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
-
-      if (_currentNode == _startNodeID || _currentNode == DTM.NULL)
-      {
+    public int next() {
+      if (_currentNode == _startNodeID || _currentNode == DTM.NULL) {
         return NULL;
-      }
-      else
-      {
+      } else {
         final int node = _currentNode;
         _currentNode = _nextsib2(node);
-
         return returnNode(makeNodeHandle(node));
       }
     }
@@ -714,8 +673,7 @@
      *
      * @param type The extended type ID being requested.
      */
-    public TypedPrecedingSiblingIterator(int type)
-    {
+    public TypedPrecedingSiblingIterator(int type) {
       _nodeType = type;
     }
 
@@ -724,8 +682,7 @@
      *
      * @return The next node handle in the iteration, or END.
      */
-    public int next()
-    {
+    public int next() {
       int node = _currentNode;
 
       final int nodeType = _nodeType;
@@ -735,8 +692,7 @@
         while (node != NULL && node != startNodeID && _exptype2(node) != nodeType) {
           node = _nextsib2(node);
         }
-      }
-      else {
+      } else {
         while (node != NULL && node != startNodeID && _exptype2(node) < DTM.NTYPES) {
           node = _nextsib2(node);
         }
@@ -745,8 +701,7 @@
       if (node == DTM.NULL || node == startNodeID) {
         _currentNode = NULL;
         return NULL;
-      }
-      else {
+      } else {
         _currentNode = _nextsib2(node);
         return returnNode(makeNodeHandle(node));
       }
@@ -755,8 +710,7 @@
     /**
      * Return the index of the last node in this iterator.
      */
-    public int getLast()
-    {
+    public int getLast() {
       if (_last != -1)
         return _last;
 
@@ -774,8 +728,7 @@
           }
           node = _nextsib2(node);
         }
-      }
-      else {
+      } else {
         while (node != NULL && node != startNodeID) {
           if (_exptype2(node) >= DTM.NTYPES) {
             last++;
@@ -860,7 +813,7 @@
      */
     public DTMAxisIterator setStartNode(int node)
     {
-//%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
+      //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
       if (node == DTMDefaultBase.ROOTNODE)
         node = getDocument();
       if (_isRestartable)
@@ -1799,9 +1752,7 @@
   // %OPT% These values are unlikely to be equal. Storing
   // them in a plain Vector is more efficient than storing in the
   // DTMStringPool because we can save the cost for hash calculation.
-  //
-  // %REVISIT% Do we need a custom class (e.g. StringVector) here?
-  protected Vector m_values;
+  protected ArrayList<String> m_values;
 
   // The current index into the m_values Vector.
   private int m_valueIndex = 0;
@@ -1881,9 +1832,8 @@
     m_buildIdIndex = buildIdIndex;
 
     // Some documents do not have attribute nodes. That is why
-    // we set the initial size of this Vector to be small and set
-    // the increment to a bigger number.
-    m_values = new Vector(32, 512);
+    // we set the initial size of this ArrayList to be small.
+    m_values = new ArrayList<>(32);
 
     m_maxNodeIndex = 1 << DTMManager.IDENT_DTM_NODE_BITS;
 
@@ -1953,10 +1903,7 @@
    * @param identity A node identity, which <em>must not</em> be equal to
    *        <code>DTM.NULL</code>
    */
-  public final int _firstch2(int identity)
-  {
-    //return m_firstch.elementAt(identity);
-
+  public final int _firstch2(int identity) {
     if (identity < m_blocksize)
       return m_firstch_map0[identity];
     else
@@ -1969,10 +1916,7 @@
    * @param identity A node identity, which <em>must not</em> be equal to
    *        <code>DTM.NULL</code>
    */
-  public final int _parent2(int identity)
-  {
-    //return m_parent.elementAt(identity);
-
+  public final int _parent2(int identity) {
     if (identity < m_blocksize)
       return m_parent_map0[identity];
     else
@@ -1985,9 +1929,7 @@
    * @param identity A node identity, which <em>must not</em> be equal to
    *        <code>DTM.NULL</code>
    */
-  public final int _type2(int identity)
-  {
-    //int eType = _exptype2(identity);
+  public final int _type2(int identity) {
     int eType;
     if (identity < m_blocksize)
       eType = m_exptype_map0[identity];
@@ -2006,12 +1948,9 @@
    * <p>This one is only used by DOMAdapter.getExpandedTypeID(int), which
    * is mostly called from the compiled translets.
    */
-  public final int getExpandedTypeID2(int nodeHandle)
-  {
+  public final int getExpandedTypeID2(int nodeHandle) {
     int nodeID = makeNodeIdentity(nodeHandle);
 
-    //return (nodeID != NULL) ? _exptype2(nodeID) : NULL;
-
     if (nodeID != NULL) {
       if (nodeID < m_blocksize)
         return m_exptype_map0[nodeID];
@@ -2026,12 +1965,10 @@
    *                 END of DTM base accessor interfaces
    *************************************************************************/
 
-
   /**
    * Return the node type from the expanded type
    */
-  public final int _exptype2Type(int exptype)
-  {
+  public final int _exptype2Type(int exptype) {
     if (NULL != exptype)
       return m_extendedTypes[exptype].getNodeType();
     else
@@ -2046,16 +1983,14 @@
    *
    * @return The prefix if there is one, or null.
    */
-  public int getIdForNamespace(String uri)
-  {
+  public int getIdForNamespace(String uri) {
      int index = m_values.indexOf(uri);
-     if (index < 0)
-     {
-       m_values.addElement(uri);
+     if (index < 0) {
+       m_values.add(uri);
        return m_valueIndex++;
+     } else {
+       return index;
      }
-     else
-       return index;
   }
 
   /**
@@ -2079,15 +2014,25 @@
    * @param attributes The specified or defaulted attributes.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#startElement
+   * @see ContentHandler#startElement
    */
-  public void startElement(String uri, String localName, String qName, Attributes attributes)
-      throws SAXException
+  public void startElement(String uri, String localName, String qName,
+                           Attributes attributes) throws SAXException
   {
-
     charactersFlush();
 
-    int exName = m_expandedNameTable.getExpandedTypeID(uri, localName, DTM.ELEMENT_NODE);
+    // in case URI and localName are empty, the input is not using the
+    // namespaces feature. Then we should take the part after the last
+    // colon of qName as localName (strip all namespace prefixes)
+    if ((uri == null || uri.isEmpty()) &&
+        (localName == null || localName.isEmpty()))
+    {
+      final int colon = qName.lastIndexOf(':');
+      localName = (colon > -1) ? qName.substring(colon + 1) : qName;
+    }
+
+    int exName = m_expandedNameTable.getExpandedTypeID(uri, localName,
+                                                       DTM.ELEMENT_NODE);
 
     int prefixIndex = (qName.length() != localName.length())
                       ? m_valuesOrPrefixes.stringToIndex(qName) : 0;
@@ -2095,7 +2040,7 @@
     int elemNode = addNode(DTM.ELEMENT_NODE, exName,
                            m_parents.peek(), m_previous, prefixIndex, true);
 
-    if(m_indexing)
+    if (m_indexing)
       indexNode(exName, elemNode);
 
     m_parents.push(elemNode);
@@ -2104,31 +2049,31 @@
     int nDecls = m_prefixMappings.size();
     String prefix;
 
-    if(!m_pastFirstElement)
-    {
+    if (!m_pastFirstElement) {
       // SPECIAL CASE: Implied declaration at root element
-      prefix="xml";
+      prefix = "xml";
       String declURL = "http://www.w3.org/XML/1998/namespace";
-      exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
-      m_values.addElement(declURL);
+      exName = m_expandedNameTable.getExpandedTypeID(null, prefix,
+                                                     DTM.NAMESPACE_NODE);
+      m_values.add(declURL);
       int val = m_valueIndex++;
       addNode(DTM.NAMESPACE_NODE, exName, elemNode,
                      DTM.NULL, val, false);
       m_pastFirstElement=true;
     }
 
-    for (int i = startDecls; i < nDecls; i += 2)
-    {
-      prefix = (String) m_prefixMappings.elementAt(i);
+    for (int i = startDecls; i < nDecls; i += 2) {
+      prefix = m_prefixMappings.elementAt(i);
 
       if (prefix == null)
         continue;
 
-      String declURL = (String) m_prefixMappings.elementAt(i + 1);
-
-      exName = m_expandedNameTable.getExpandedTypeID(null, prefix, DTM.NAMESPACE_NODE);
-
-      m_values.addElement(declURL);
+      String declURL = m_prefixMappings.elementAt(i + 1);
+
+      exName = m_expandedNameTable.getExpandedTypeID(null, prefix,
+                                                     DTM.NAMESPACE_NODE);
+
+      m_values.add(declURL);
       int val = m_valueIndex++;
 
       addNode(DTM.NAMESPACE_NODE, exName, elemNode, DTM.NULL, val, false);
@@ -2136,28 +2081,37 @@
 
     int n = attributes.getLength();
 
-    for (int i = 0; i < n; i++)
-    {
+    for (int i = 0; i < n; i++) {
       String attrUri = attributes.getURI(i);
+      String attrLocalName = attributes.getLocalName(i);
       String attrQName = attributes.getQName(i);
       String valString = attributes.getValue(i);
 
+      // in case URI and localName are empty, the input is not using the
+      // namespaces feature. Then we should take the part after the last
+      // colon of qName as localName (strip all namespace prefixes)
+      // When the URI is empty but localName has colons then we can also
+      // assume non namespace aware and prefixes can be stripped
+      if (attrUri == null || attrUri.isEmpty()) {
+        if (attrLocalName == null || attrLocalName.isEmpty()) {
+          final int colon = attrQName.lastIndexOf(':');
+          attrLocalName = (colon > -1) ? attrQName.substring(colon + 1) : attrQName;
+        } else {
+          final int colon = attrLocalName.lastIndexOf(':');
+          attrLocalName = (colon > -1) ? attrLocalName.substring(colon + 1) : attrLocalName;
+        }
+      }
+
       int nodeType;
-
-      String attrLocalName = attributes.getLocalName(i);
-
-      if ((null != attrQName)
-              && (attrQName.equals("xmlns")
-                  || attrQName.startsWith("xmlns:")))
+      if ((null != attrQName) &&
+          (attrQName.equals("xmlns") || attrQName.startsWith("xmlns:")))
       {
         prefix = getPrefix(attrQName, attrUri);
         if (declAlreadyDeclared(prefix))
           continue;  // go to the next attribute.
 
         nodeType = DTM.NAMESPACE_NODE;
-      }
-      else
-      {
+      } else {
         nodeType = DTM.ATTRIBUTE_NODE;
 
         if (m_buildIdIndex && attributes.getType(i).equalsIgnoreCase("ID"))
@@ -2166,36 +2120,31 @@
 
       // Bit of a hack... if somehow valString is null, stringToIndex will
       // return -1, which will make things very unhappy.
-      if(null == valString)
+      if (null == valString)
         valString = "";
 
-      m_values.addElement(valString);
+      m_values.add(valString);
       int val = m_valueIndex++;
 
-      if (attrLocalName.length() != attrQName.length())
-      {
-
+      if (attrLocalName.length() != attrQName.length()) {
         prefixIndex = m_valuesOrPrefixes.stringToIndex(attrQName);
-
         int dataIndex = m_data.size();
-
         m_data.addElement(prefixIndex);
         m_data.addElement(val);
-
         val = -dataIndex;
       }
 
-      exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName, nodeType);
-      addNode(nodeType, exName, elemNode, DTM.NULL, val,
-                     false);
+      exName = m_expandedNameTable.getExpandedTypeID(attrUri, attrLocalName,
+                                                     nodeType);
+      addNode(nodeType, exName, elemNode, DTM.NULL, val, false);
     }
 
-    if (null != m_wsfilter)
-    {
-      short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode), this);
-      boolean shouldStrip = (DTMWSFilter.INHERIT == wsv)
-                            ? getShouldStripWhitespace()
-                            : (DTMWSFilter.STRIP == wsv);
+    if (null != m_wsfilter) {
+      short wsv = m_wsfilter.getShouldStripSpace(makeNodeHandle(elemNode),
+                                                 this);
+      boolean shouldStrip = (DTMWSFilter.INHERIT == wsv) ?
+                            getShouldStripWhitespace() :
+                            (DTMWSFilter.STRIP == wsv);
 
       pushShouldStripWhitespace(shouldStrip);
     }
@@ -2223,7 +2172,7 @@
    *        empty string if qualified names are not available.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#endElement
+   * @see ContentHandler#endElement
    */
   public void endElement(String uri, String localName, String qName)
           throws SAXException
@@ -2257,9 +2206,7 @@
    * @param length The number of characters to use from the array.
    * @throws SAXException The application may raise an exception.
    */
-  public void comment(char ch[], int start, int length) throws SAXException
-  {
-
+  public void comment(char ch[], int start, int length) throws SAXException {
     if (m_insideDTD)      // ignore comments if we're inside the DTD
       return;
 
@@ -2267,7 +2214,7 @@
 
     // %OPT% Saving the comment string in a Vector has a lower cost than
     // saving it in DTMStringPool.
-    m_values.addElement(new String(ch, start, length));
+    m_values.add(new String(ch, start, length));
     int dataIndex = m_valueIndex++;
 
     m_previous = addNode(DTM.COMMENT_NODE, DTM.COMMENT_NODE,
@@ -2279,13 +2226,10 @@
    *
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#startDocument
+   * @see ContentHandler#startDocument
    */
-  public void startDocument() throws SAXException
-  {
-
-    int doc = addNode(DTM.DOCUMENT_NODE,
-                      DTM.DOCUMENT_NODE,
+  public void startDocument() throws SAXException {
+    int doc = addNode(DTM.DOCUMENT_NODE, DTM.DOCUMENT_NODE,
                       DTM.NULL, DTM.NULL, 0, true);
 
     m_parents.push(doc);
@@ -2299,10 +2243,9 @@
    *
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#endDocument
+   * @see ContentHandler#endDocument
    */
-  public void endDocument() throws SAXException
-  {
+  public void endDocument() throws SAXException {
     super.endDocument();
 
     // Add a NULL entry to the end of the node arrays as
@@ -2334,16 +2277,15 @@
    * @return The index identity of the node that was added.
    */
   protected final int addNode(int type, int expandedTypeID,
-                        int parentIndex, int previousSibling,
-                        int dataOrPrefix, boolean canHaveFirstChild)
+                              int parentIndex, int previousSibling,
+                              int dataOrPrefix, boolean canHaveFirstChild)
   {
     // Common to all nodes:
     int nodeIndex = m_size++;
 
     // Have we overflowed a DTM Identity's addressing range?
     //if(m_dtmIdent.size() == (nodeIndex>>>DTMManager.IDENT_DTM_NODE_BITS))
-    if (nodeIndex == m_maxNodeIndex)
-    {
+    if (nodeIndex == m_maxNodeIndex) {
       addNewDTMID(nodeIndex);
       m_maxNodeIndex += (1 << DTMManager.IDENT_DTM_NODE_BITS);
     }
@@ -2366,8 +2308,7 @@
     // is called, to handle successive characters() events.
 
     // Special handling by type: Declare namespaces, attach first child
-    switch(type)
-    {
+    switch(type) {
     case DTM.NAMESPACE_NODE:
       declareNamespaceInContext(parentIndex,nodeIndex);
       break;
@@ -2376,8 +2317,7 @@
     default:
       if (DTM.NULL != previousSibling) {
         m_nextsib.setElementAt(nodeIndex,previousSibling);
-      }
-      else if (DTM.NULL != parentIndex) {
+      } else if (DTM.NULL != parentIndex) {
         m_firstch.setElementAt(nodeIndex,parentIndex);
       }
       break;
@@ -2390,16 +2330,12 @@
    * Check whether accumulated text should be stripped; if not,
    * append the appropriate flavor of text/cdata node.
    */
-  protected final void charactersFlush()
-  {
-
-    if (m_textPendingStart >= 0)  // -1 indicates no-text-in-progress
-    {
+  protected final void charactersFlush() {
+    if (m_textPendingStart >= 0) { // -1 indicates no-text-in-progress
       int length = m_chars.size() - m_textPendingStart;
       boolean doStrip = false;
 
-      if (getShouldStripWhitespace())
-      {
+      if (getShouldStripWhitespace()) {
         doStrip = m_chars.isWhitespace(m_textPendingStart, length);
       }
 
@@ -2412,19 +2348,19 @@
           // If the offset and length do not exceed the given limits
           // (offset < 2^21 and length < 2^10), then save both the offset
           // and length in a bitwise encoded value.
-          if (length <= TEXT_LENGTH_MAX
-                  && m_textPendingStart <= TEXT_OFFSET_MAX) {
+          if (length <= TEXT_LENGTH_MAX &&
+              m_textPendingStart <= TEXT_OFFSET_MAX) {
             m_previous = addNode(m_coalescedTextType, DTM.TEXT_NODE,
-                             m_parents.peek(), m_previous,
-                             length + (m_textPendingStart << TEXT_LENGTH_BITS),
-                             false);
+                                 m_parents.peek(), m_previous,
+                                 length + (m_textPendingStart << TEXT_LENGTH_BITS),
+                                 false);
 
           } else {
             // Store offset and length in the m_data array if one exceeds
             // the given limits. Use a negative dataIndex as an indication.
             int dataIndex = m_data.size();
             m_previous = addNode(m_coalescedTextType, DTM.TEXT_NODE,
-                               m_parents.peek(), m_previous, -dataIndex, false);
+                                 m_parents.peek(), m_previous, -dataIndex, false);
 
             m_data.addElement(m_textPendingStart);
             m_data.addElement(length);
@@ -2452,7 +2388,7 @@
    *             none is supplied.
    * @throws SAXException Any SAX exception, possibly
    *            wrapping another exception.
-   * @see org.xml.sax.ContentHandler#processingInstruction
+   * @see ContentHandler#processingInstruction
    */
   public void processingInstruction(String target, String data)
           throws SAXException
@@ -2467,7 +2403,7 @@
                          -dataIndex, false);
 
     m_data.addElement(m_valuesOrPrefixes.stringToIndex(target));
-    m_values.addElement(data);
+    m_values.add(data);
     m_data.addElement(m_valueIndex++);
 
   }
@@ -2865,9 +2801,9 @@
       }
 
       if (m_xstrf != null)
-        return m_xstrf.newstr((String)m_values.elementAt(dataIndex));
+        return m_xstrf.newstr(m_values.get(dataIndex));
       else
-        return new XMLStringDefault((String)m_values.elementAt(dataIndex));
+        return new XMLStringDefault(m_values.get(dataIndex));
     }
   }
 
@@ -2966,7 +2902,7 @@
         dataIndex = m_data.elementAt(dataIndex + 1);
       }
 
-      return (String)m_values.elementAt(dataIndex);
+      return m_values.get(dataIndex);
     }
   }
 
@@ -3106,7 +3042,7 @@
         dataIndex = m_data.elementAt(dataIndex + 1);
       }
 
-      String str = (String)m_values.elementAt(dataIndex);
+      String str = m_values.get(dataIndex);
 
       if(normalize)
         FastStringBuffer.sendNormalizedSAXcharacters(str.toCharArray(),
@@ -3160,7 +3096,7 @@
         dataIndex = m_data.elementAt(dataIndex + 1);
       }
 
-      return (String)m_values.elementAt(dataIndex);
+      return m_values.get(dataIndex);
     }
   }
 
@@ -3202,8 +3138,7 @@
         if (uri.length() == 0) {
             handler.startElement(name);
             return name;
-        }
-        else {
+        } else {
             int qnameIndex = m_dataOrQName.elementAt(nodeID);
 
             if (qnameIndex == 0) {
@@ -3223,14 +3158,12 @@
             String prefix;
             if (prefixIndex > 0) {
                 prefix = qName.substring(0, prefixIndex);
-            }
-            else {
+            } else {
                 prefix = null;
             }
             handler.namespaceAfterStartElement(prefix, uri);
             return qName;
         }
-
     }
 
     /**
@@ -3285,7 +3218,7 @@
                 dataIndex = m_data.elementAt(dataIndex + 1);
             }
 
-            String nodeValue = (String)m_values.elementAt(dataIndex);
+            String nodeValue = m_values.get(dataIndex);
 
             handler.namespaceAfterStartElement(nodeName, nodeValue);
 
@@ -3335,7 +3268,6 @@
     }
 
 
-
     /**
      * Copy an Attribute node to a SerializationHandler
      *
@@ -3347,14 +3279,6 @@
         SerializationHandler handler)
         throws SAXException
     {
-        /*
-            final String uri = getNamespaceName(node);
-            if (uri.length() != 0) {
-                final String prefix = getPrefix(node);
-                handler.namespaceAfterStartElement(prefix, uri);
-            }
-            handler.addAttribute(getNodeName(node), getNodeValue(node));
-        */
         final ExtendedType extType = m_extendedTypes[exptype];
         final String uri = extType.getNamespace();
         final String localName = extType.getLocalName();
@@ -3377,7 +3301,7 @@
             }
 
         String nodeName = (prefix != null) ? qname : localName;
-        String nodeValue = (String)m_values.elementAt(valueIndex);
+        String nodeValue = m_values.get(valueIndex);
 
         handler.addAttribute(uri, localName, nodeName, "CDATA", nodeValue);
     }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@
     }
 
     /**
-     * Returns the catalog attribute as an URI String.
+     * Returns the catalog attribute as a URI String.
      * @return The value of the catalog attribute
      */
     String getCatalogId() {
@@ -66,7 +66,7 @@
     }
 
     /**
-     * Returns the catalog attribute as an URI.
+     * Returns the catalog attribute as a URI.
      * @return The value of the catalog attribute
      */
     URI getCatalogURI() {
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Objects;
+import static javax.xml.catalog.CatalogMessages.ERR_INVALID_ARGUMENT;
 
 /**
  * Represents a general Catalog entry.
@@ -210,13 +211,12 @@
      * @param arg The name of the argument
      * @param uri The URI to be verified
      * @return The URI created from the specified uri
-     * @throws IllegalArgumentException if the specified uri is null,
-     * or an URL can not be created based on the specified base and uri
+     * @throws NullPointerException if the specified uri is null
+     * @throws IllegalArgumentException if a URL can not be created based on
+     * the specified base and uri
      */
     URL verifyURI(String arg, URL base, String uri) {
-        if (uri == null) {
-            CatalogMessages.reportIAE(new Object[]{uri, arg}, null);
-        }
+        CatalogMessages.reportNPEOnNull(arg, uri);
 
         URL url = null;
         uri = Normalizer.normalizeURI(uri);
@@ -228,32 +228,9 @@
                 url = new URL(uri);
             }
         } catch (MalformedURLException e) {
-            CatalogMessages.reportIAE(new Object[]{uri, arg}, e);
+            CatalogMessages.reportIAE(ERR_INVALID_ARGUMENT,
+                    new Object[]{uri, arg}, e);
         }
         return url;
     }
-
-    /**
-     * Construct an absolute URI from a relative one, using the current base
-     * URI.
-     *
-     * @param sysid The (possibly relative) system identifier
-     * @return The system identifier made absolute with respect to the current
-     * {@link #base}.
-     */
-    protected String makeAbsolute(String sysid) {
-        URL local = null;
-
-        sysid = Util.fixSlashes(sysid);
-        /**
-         * try { local = new URL(base, sysid); } catch (MalformedURLException e)
-         * { catalogManager.debug.message(1, "Malformed URL on system
-         * identifier", sysid); }
-         */
-        if (local != null) {
-            return local.toString();
-        } else {
-            return sysid;
-        }
-    }
 }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
  * <ul>
  * <li>Locate the external resources with a public or system identifier;
  * </li>
- * <li>Locate an alternate URI reference with an URI.
+ * <li>Locate an alternate URI reference with a URI.
  * </li>
  * </ul>
  * <p>
@@ -84,7 +84,7 @@
      *
      * @param systemId the system identifier of the entity to be matched
      *
-     * @return an URI string if a mapping is found, or null otherwise
+     * @return a URI string if a mapping is found, or null otherwise
      */
     public String matchSystem(String systemId);
 
@@ -108,7 +108,7 @@
      *
      * @param publicId the public identifier of the entity to be matched
      * @see CatalogFeatures.Feature
-     * @return an URI string if a mapping is found, or null otherwise
+     * @return a URI string if a mapping is found, or null otherwise
      */
     public String matchPublic(String publicId);
 
@@ -134,7 +134,7 @@
      *
      * @param uri the URI reference of the entity to be matched
      *
-     * @return an URI string if a mapping is found, or null otherwise
+     * @return a URI string if a mapping is found, or null otherwise
      */
     public String matchURI(String uri);
 
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,14 +56,14 @@
  *
  * <tr>
  * <td><a name="FILES">FILES</a></td>
- * <td>A semicolon-delimited list of catalog files. Relative file paths are
- * considered relative to ${user.dir}.
+ * <td>A semicolon-delimited list of URIs to locate the catalog files.
+ * The URIs must be absolute and have a URL protocol handler for the URI scheme.
  * </td>
  * <td>javax.xml.catalog.files</td>
  * <td>javax.xml.catalog.files</td>
  * <td>javax.xml.catalog.files</td>
  * <td>String</td>
- * <td>File paths</td>
+ * <td>URIs</td>
  * <td>
  * Reads the first catalog as the current catalog; Loads others if no match
  * is found in the current catalog including delegate catalogs if any.
@@ -170,7 +170,7 @@
  * Properties set through the Catalog API override those that may have been set
  * by system properties and/or in {@code jaxp.properties}. In case of multiple
  * interfaces, the latest in a procedure shall take preference. For
- * {@link Feature#FILES}, this means that the path(s) specified through the methods
+ * {@link Feature#FILES}, this means that the URI(s) specified through the methods
  * of the {@link CatalogManager} will override any that may have been entered
  * through the {@link Builder}.
  *
@@ -188,7 +188,7 @@
  * in the following sample code:
  * <pre>{@code
                 CatalogFeatures f = CatalogFeatures.builder()
-                        .with(Feature.FILES, "catalog.xml")
+                        .with(Feature.FILES, "file:///etc/xml/catalog")
                         .with(Feature.PREFER, "public")
                         .with(Feature.DEFER, "true")
                         .with(Feature.RESOLVE, "ignore")
@@ -202,14 +202,14 @@
  * Schema Validation ({@link javax.xml.validation}), and XML Transformation
  * ({@link javax.xml.transform}). The features described above can be set through JAXP
  * factories or processors that define a setProperty or setAttribute interface.
- * For example, the following code snippet sets a path to a catalog file on a SAX
+ * For example, the following code snippet sets a URI to a catalog file on a SAX
  * parser through the {@code javax.xml.catalog.files} property:
  * <p>
  * <pre>{@code
  *      SAXParserFactory spf = SAXParserFactory.newInstance();
  *      spf.setFeature(XMLConstants.USE_CATALOG, true); [1]
  *      SAXParser parser = spf.newSAXParser();
- *      parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "catalog.xml");
+ *      parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "file:///etc/xml/catalog");
  * }</pre>
  * <p>
  * [1] Note that this statement is not required since the default value of
@@ -275,7 +275,7 @@
    The following XInclude element:
    <xi:include href="http://openjdk.java.net/xml/disclaimer.xml"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xml/disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
    or
    <uriSuffix uriSuffix="disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
@@ -291,7 +291,7 @@
     <xsd:import namespace="http://openjdk.java.net/xsd/XSDImport_person"
                 schemaLocation="http://openjdk.java.net/xsd/XSDImport_person.xsd"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsd/XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
    or
    <uriSuffix uriSuffix="XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
@@ -308,7 +308,7 @@
    The following include element:
    <xsd:include schemaLocation="http://openjdk.java.net/xsd/XSDInclude_person.xsd"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsd/XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
    or
    <uriSuffix uriSuffix="XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
@@ -323,7 +323,7 @@
    The following include element:
    <xsl:include href="http://openjdk.java.net/xsl/include.xsl"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsl/include.xsl" uri="file:///pathto/local/include.xsl"/>
    or
    <uriSuffix uriSuffix="include.xsl" uri="file:///pathto/local/include.xsl"/>
@@ -338,7 +338,7 @@
    The document in the following element:
    <xsl:variable name="dummy" select="document('http://openjdk.java.net/xsl/list.xml')"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsl/list.xml" uri="file:///pathto/local/list.xml"/>
    or
    <uriSuffix uriSuffix="list.xml" uri="file:///pathto/local/list.xml"/>
@@ -559,7 +559,7 @@
         values = new String[Feature.values().length];
         states = new State[Feature.values().length];
         for (Feature cf : Feature.values()) {
-            setProperty(cf.ordinal(), State.DEFAULT, cf.defaultValue());
+            setProperty(cf, State.DEFAULT, cf.defaultValue());
         }
         //read system properties or jaxp.properties
         readSystemProperties();
@@ -571,52 +571,27 @@
      */
     private void setProperties(Builder builder) {
         builder.values.entrySet().stream().forEach((entry) -> {
-            setProperty(entry.getKey().ordinal(), State.APIPROPERTY, entry.getValue());
+            setProperty(entry.getKey(), State.APIPROPERTY, entry.getValue());
         });
     }
     /**
-     * Sets the value of a property by its index, updates only if it shall override.
+     * Sets the value of a property, updates only if it shall override.
      *
      * @param index the index of the property
      * @param state the state of the property
      * @param value the value of the property
      * @throws IllegalArgumentException if the value is invalid
      */
-    private void setProperty(int index, State state, String value) {
+    private void setProperty(Feature feature, State state, String value) {
+        int index = feature.ordinal();
         if (value != null && value.length() != 0) {
-            if (index == Feature.PREFER.ordinal()) {
-                if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.PREFER.name()}, null);
-                }
-            } else if (index == Feature.DEFER.ordinal()) {
-                if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.DEFER.name()}, null);
-                }
-            } else if (index == Feature.RESOLVE.ordinal()) {
-                if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
-                         && !value.equals(RESOLVE_IGNORE)) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.RESOLVE.name()}, null);
-                }
-            } else if (index == Feature.FILES.ordinal()) {
-                try {
-                    String[] catalogFile = value.split(";[ ]*");
-                    for (String temp : catalogFile) {
-                        if (Util.verifyAndGetURI(temp, null) == null) {
-                            CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
-                        }
-                    }
-                }catch (MalformedURLException | URISyntaxException | IllegalArgumentException ex) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, ex);
-                }
+            if (state != State.APIPROPERTY) {
+                Util.validateFeatureInput(feature, value);
             }
             if (states[index] == null || state.compareTo(states[index]) >= 0) {
                 values[index] = value;
                 states[index] = state;
             }
-        } else {
-            if (state == State.SYSTEMPROPERTY || state == State.JAXPDOTPROPERTIES) {
-                CatalogMessages.reportIAE(new Object[]{value, Feature.values()[index].name()}, null);
-            }
         }
     }
 
@@ -639,13 +614,13 @@
         if (cf.hasSystemProperty()) {
             String value = SecuritySupport.getSystemProperty(sysPropertyName);
             if (value != null && !value.equals("")) {
-                setProperty(cf.ordinal(), State.SYSTEMPROPERTY, value);
+                setProperty(cf, State.SYSTEMPROPERTY, value);
                 return true;
             }
 
             value = SecuritySupport.readJAXPProperty(sysPropertyName);
             if (value != null && !value.equals("")) {
-                setProperty(cf.ordinal(), State.JAXPDOTPROPERTIES, value);
+                setProperty(cf, State.JAXPDOTPROPERTIES, value);
                 return true;
             }
         }
@@ -685,9 +660,7 @@
          * property
          */
         public Builder with(Feature feature, String value) {
-            if (value == null || value.length() == 0) {
-                CatalogMessages.reportIAE(new Object[]{value, feature.name()}, null);
-            }
+            Util.validateFeatureInput(feature, value);
             values.put(feature, value);
             return this;
         }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
 
     /*
      A list of catalog entry files from the input, excluding the current catalog.
-     Paths in the List are normalized.
+     URIs in the List are verified during input validation or property retrieval.
      */
     List<String> inputFiles;
 
@@ -86,43 +86,44 @@
     SAXParser parser;
 
     /**
-     * Construct a Catalog with specified path.
+     * Construct a Catalog with specified URI.
      *
-     * @param file The path to a catalog file.
+     * @param uris the uri(s) to one or more catalogs
      * @throws CatalogException If an error happens while parsing the specified
      * catalog file.
      */
-    public CatalogImpl(CatalogFeatures f, String... file) throws CatalogException {
-        this(null, f, file);
+    public CatalogImpl(CatalogFeatures f, URI... uris) throws CatalogException {
+        this(null, f, uris);
     }
 
     /**
-     * Construct a Catalog with specified path.
+     * Construct a Catalog with specified URI.
      *
      * @param parent The parent catalog
-     * @param file The path to a catalog file.
+     * @param uris the uri(s) to one or more catalogs
      * @throws CatalogException If an error happens while parsing the specified
      * catalog file.
      */
-    public CatalogImpl(CatalogImpl parent, CatalogFeatures f, String... file) throws CatalogException {
+    public CatalogImpl(CatalogImpl parent, CatalogFeatures f, URI... uris) throws CatalogException {
         super(CatalogEntryType.CATALOG, parent);
         if (f == null) {
             throw new NullPointerException(
                     formatMessage(CatalogMessages.ERR_NULL_ARGUMENT, new Object[]{"CatalogFeatures"}));
         }
 
-        if (file.length > 0) {
-            CatalogMessages.reportNPEOnNull("The path to the catalog file", file[0]);
-        }
-
         init(f);
 
         //Path of catalog files
-        String[] catalogFile = file;
-        if (level == 0 && file.length == 0) {
+        String[] catalogFile = null;
+        if (level == 0 && uris.length == 0) {
             String files = features.get(Feature.FILES);
             if (files != null) {
-                catalogFile = files.split(";[ ]*");
+                catalogFile = files.split(";");
+            }
+        } else {
+            catalogFile = new String[uris.length];
+            for (int i=0; i<uris.length; i++) {
+                catalogFile[i] = uris[i].toASCIIString();
             }
         }
 
@@ -134,10 +135,10 @@
             int start = 0;
             URI uri = null;
             for (String temp : catalogFile) {
-                uri = getSystemId(temp);
+                uri = URI.create(temp);
                 start++;
                 if (verifyCatalogFile(uri)) {
-                    systemId = uri.toASCIIString();
+                    systemId = temp;
                     try {
                         baseURI = new URL(systemId);
                     } catch (MalformedURLException e) {
@@ -294,29 +295,6 @@
     }
 
     /**
-     * Resolves the specified file path to an absolute systemId. If it is
-     * relative, it shall be resolved using the base or user.dir property if
-     * base is not specified.
-     *
-     * @param file The specified file path
-     * @return The systemId of the file
-     * @throws CatalogException if the specified file path can not be converted
-     * to a system id
-     */
-    private URI getSystemId(String file) {
-        URI temp = null;
-
-        try {
-            temp = Util.verifyAndGetURI(file, baseURI);
-        } catch (MalformedURLException | URISyntaxException | IllegalArgumentException e) {
-            CatalogMessages.reportRunTimeError(CatalogMessages.ERR_INVALID_PATH,
-                    new Object[]{file}, e);
-        }
-
-        return temp;
-    }
-
-    /**
      * Returns a SAXParser instance
      * @return a SAXParser instance
      * @throws CatalogException if constructing a SAXParser failed
@@ -394,7 +372,7 @@
                 //Check the input list
                 if (c == null && inputFiles != null) {
                     while (c == null && inputFilesIndex < inputFiles.size()) {
-                        c = getCatalog(getSystemId(inputFiles.get(inputFilesIndex++)));
+                        c = getCatalog(URI.create(inputFiles.get(inputFilesIndex++)));
                     }
                 }
 
@@ -436,8 +414,8 @@
 
         //loads catalogs from the input list
         if (inputFiles != null) {
-            inputFiles.stream().forEach((file) -> {
-                getCatalog(getSystemId(file));
+            inputFiles.stream().forEach((uri) -> {
+                getCatalog(URI.create(uri));
             });
         }
     }
@@ -454,12 +432,11 @@
         }
 
         CatalogImpl c = null;
-        String path = uri.toASCIIString();
 
         if (verifyCatalogFile(uri)) {
-            c = getLoadedCatalog(path);
+            c = getLoadedCatalog(uri.toASCIIString());
             if (c == null) {
-                c = new CatalogImpl(this, features, path);
+                c = new CatalogImpl(this, features, uri);
                 c.load();
             }
         }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
  */
 package javax.xml.catalog;
 
+import java.net.URI;
 
 /**
  * The Catalog Manager manages the creation of XML Catalogs and Catalog Resolvers.
@@ -39,30 +40,36 @@
 
     /**
      * Creates a {@code Catalog} object using the specified feature settings and
-     * path to one or more catalog files.
+     * uri(s) to one or more catalog files.
      * <p>
-     * If {@code paths} is empty, system property {@code javax.xml.catalog.files}
-     * will be read to locate the initial list of catalog files.
+     * If {@code uris} is empty, system property {@code javax.xml.catalog.files},
+     * as defined in {@link CatalogFeatures}, will be read to locate the initial
+     * list of catalog files.
      * <p>
-     * If more than one catalog files are specified through the paths argument or
+     * If multiple catalog files are specified through the {@code uris} argument or
      * {@code javax.xml.catalog.files} property, the first entry is considered
      * the main catalog, while others are treated as alternative catalogs after
      * those referenced by the {@code nextCatalog} elements in the main catalog.
      * <p>
      * As specified in
      * <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html#s.res.fail">
-     * XML Catalogs, OASIS Standard V1.1</a>, invalid path entries will be ignored.
-     * No error will be reported. In case all entries are invalid, the resolver
-     * will return as no mapping is found.
+     * XML Catalogs, OASIS Standard V1.1</a>, if a catalog entry is invalid, it
+     * is ignored. In case all entries are invalid, the resulting Catalog object
+     * will contain no Catalog elements. Any matching operation using the Catalog
+     * will return null.
      *
      * @param features the catalog features
-     * @param paths path(s) to one or more catalogs.
+     * @param uris uri(s) to one or more catalogs.
      *
      * @return an instance of a {@code Catalog}
+     * @throws IllegalArgumentException if either the URIs are not absolute
+     * or do not have a URL protocol handler for the URI scheme
      * @throws CatalogException If an error occurs while parsing the catalog
+     * @throws SecurityException if access to the resource is denied by the security manager
      */
-    public static Catalog catalog(CatalogFeatures features, String... paths) {
-        CatalogImpl catalog = new CatalogImpl(features, paths);
+    public static Catalog catalog(CatalogFeatures features, URI... uris) {
+        Util.validateUrisSyntax(uris);
+        CatalogImpl catalog = new CatalogImpl(features, uris);
         catalog.load();
         return catalog;
     }
@@ -80,30 +87,36 @@
 
     /**
      * Creates an instance of a {@code CatalogResolver} using the specified feature
-     * settings and path to one or more catalog files.
+     * settings and uri(s) to one or more catalog files.
      * <p>
-     * If {@code paths} is empty, system property {@code javax.xml.catalog.files}
-     * will be read to locate the initial list of catalog files.
+     * If {@code uris} is empty, system property {@code javax.xml.catalog.files},
+     * as defined in {@link CatalogFeatures}, will be read to locate the initial
+     * list of catalog files.
      * <p>
-     * If more than one catalog files are specified through the paths argument or
+     * If multiple catalog files are specified through the {@code uris} argument or
      * {@code javax.xml.catalog.files} property, the first entry is considered
      * the main catalog, while others are treated as alternative catalogs after
      * those referenced by the {@code nextCatalog} elements in the main catalog.
      * <p>
      * As specified in
      * <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html#s.res.fail">
-     * XML Catalogs, OASIS Standard V1.1</a>, invalid path entries will be ignored.
-     * No error will be reported. In case all entries are invalid, the resolver
-     * will return as no mapping is found.
+     * XML Catalogs, OASIS Standard V1.1</a>, if a catalog entry is invalid, it
+     * is ignored. In case all entries are invalid, the resulting CatalogResolver
+     * object will contain no valid catalog. Any resolution operation using the
+     * resolver therefore will return as no mapping is found. See {@link CatalogResolver}
+     * for the behavior when no mapping is found.
      *
      * @param features the catalog features
-     * @param paths the path(s) to one or more catalogs
+     * @param uris the uri(s) to one or more catalogs
      *
      * @return an instance of a {@code CatalogResolver}
+     * @throws IllegalArgumentException if either the URIs are not absolute
+     * or do not have a URL protocol handler for the URI scheme
      * @throws CatalogException If an error occurs while parsing the catalog
+     * @throws SecurityException if access to the resource is denied by the security manager
      */
-    public static CatalogResolver catalogResolver(CatalogFeatures features, String... paths) {
-        Catalog catalog = catalog(features, paths);
+    public static CatalogResolver catalogResolver(CatalogFeatures features, URI... uris) {
+        Catalog catalog = catalog(features, uris);
         return new CatalogResolverImpl(catalog);
     }
 }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,11 @@
  */
 package javax.xml.catalog;
 
-import jdk.xml.internal.SecuritySupport;
+import java.net.URI;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import jdk.xml.internal.SecuritySupport;
 
 /**
  * Catalog Error messages
@@ -38,6 +39,8 @@
 
     public static final String ERR_INVALID_CATALOG = "InvalidCatalog";
     public static final String ERR_INVALID_ENTRY_TYPE = "InvalidEntryType";
+    public static final String ERR_URI_NOTABSOLUTE = "UriNotAbsolute";
+    public static final String ERR_URI_NOTVALIDURL = "UriNotValidUrl";
     public static final String ERR_INVALID_ARGUMENT = "InvalidArgument";
     public static final String ERR_NULL_ARGUMENT = "NullArgument";
     public static final String ERR_CIRCULAR_REFERENCE = "CircularReference";
@@ -120,7 +123,7 @@
      * @param name the name of the argument
      * @param value the value of the argument
      */
-    static void reportNPEOnNull(String name, String value) {
+    static void reportNPEOnNull(String name, Object value) {
         if (value == null) {
             throw new NullPointerException(
                     formatMessage(ERR_NULL_ARGUMENT, new Object[]{name}));
@@ -132,9 +135,9 @@
      * @param arguments the arguments for formating the error message
      * @param cause the cause if any
      */
-    static void reportIAE(Object[] arguments, Throwable cause) {
+    static void reportIAE(String key, Object[] arguments, Throwable cause) {
         throw new IllegalArgumentException(
-                formatMessage(ERR_INVALID_ARGUMENT, arguments), cause);
+                formatMessage(key, arguments), cause);
     }
 
     /**
@@ -174,7 +177,7 @@
 
     /**
      * Returns sanitized URI.
-     * @param uri an URI to be sanitized
+     * @param uri a URI to be sanitized
      */
     static String sanitize(String uri) {
         if (uri == null) {
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -31,6 +31,8 @@
 CircularReference = Circular reference is not allowed: ''{0}''.
 
 #errors
+UriNotAbsolute = The specified URI ''{0}'' is not absolute.
+UriNotValidUrl = The specified URI ''{0}'' is not a valid URL.
 InvalidArgument = The specified argument ''{0}'' (case sensitive) for ''{1}'' is not valid.
 NullArgument = The argument ''{0}'' can not be null.
 InvalidPath = The path ''{0}'' is invalid.
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,6 @@
 package javax.xml.catalog;
 
 import java.io.StringReader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import javax.xml.catalog.BaseEntry.CatalogEntryType;
 import javax.xml.parsers.SAXParser;
 import javax.xml.transform.Source;
@@ -94,25 +90,6 @@
         this.parser = parser;
     }
 
-    /**
-     * Returns when the specified path is valid.
-     * @param path a path
-     * @return true if the path is valid, false otherwise
-     */
-    boolean isValidPath(String path) {
-        boolean valid = true;
-        try {
-            Path p = Paths.get(new URI(path));
-            if (!p.toFile().exists()) {
-                valid = false;
-            }
-        } catch (URISyntaxException ex) {
-            valid = false;
-        }
-
-        return valid;
-    }
-
     @Override
     public void startElement(String namespaceURI,
             String localName,
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
  * {@link javax.xml.stream.XMLResolver} and {@link org.w3c.dom.ls.LSResourceResolver}
  * however, make no such distinction.
  * In consistent with the existing Java API, this CatalogResolver recognizes a
- * system identifier as an URI and will search both {@code system} and {@code uri}
+ * system identifier as a URI and will search both {@code system} and {@code uri}
  * entries in a catalog in order to find a matching entry.
  * <p>
  * The search is started in the current catalog. If a match is found,
@@ -137,9 +137,9 @@
      * with the specified {@code href} attribute. The {@code href} attribute will
      * be used literally, with no attempt to be made absolute to the {@code base}.
      * <p>
-     * If the value is an URN, the {@code href} attribute is recognized as a
+     * If the value is a URN, the {@code href} attribute is recognized as a
      * {@code publicId}, and used to search {@code public} entries.
-     * If the value is an URI, it is taken as a {@code systemId}, and used to
+     * If the value is a URI, it is taken as a {@code systemId}, and used to
      * search both {@code system} and {@code uri} entries.
      *
      *
@@ -219,7 +219,7 @@
      * @param publicId  the public identifier of the external entity being
      *   referenced, or {@code null} if no public identifier was
      *   supplied or if the resource is not an entity.
-     * @param systemId  the system identifier, an URI reference of the
+     * @param systemId  the system identifier, a URI reference of the
      *   external resource being referenced
      * @param baseUri  the absolute base URI, not used by the CatalogResolver
      *
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
         systemId = Normalizer.normalizeURI(Util.getNotNullOrEmpty(systemId));
         publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(Util.getNotNullOrEmpty(publicId)));
 
-        //check whether systemId is an urn
+        //check whether systemId is a urn
         if (systemId != null && systemId.startsWith(Util.URN)) {
             systemId = Normalizer.decodeURN(systemId);
             if (publicId != null && !publicId.equals(systemId)) {
@@ -123,7 +123,7 @@
             return null;
         }
 
-        //check whether uri is an urn
+        //check whether uri is a urn
         if (uri != null && uri.startsWith(Util.URN)) {
             String publicId = Normalizer.decodeURN(uri);
             if (publicId != null) {
@@ -131,7 +131,7 @@
             }
         }
 
-        //if no match with a public id, continue search for an URI
+        //if no match with a public id, continue search for a URI
         if (result == null) {
             //remove fragment if any.
             int hashPos = uri.indexOf("#");
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 package javax.xml.catalog;
 
 import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -217,7 +215,7 @@
      * @param systemId The system identifier of the external entity being
      * referenced.
      *
-     * @return An URI string if a mapping is found, or null otherwise.
+     * @return a URI string if a mapping is found, or null otherwise.
      */
     public String matchSystem(String systemId) {
         systemEntrySearched = true;
@@ -285,7 +283,7 @@
      * @param publicId The public identifier of the external entity being
      * referenced.
      *
-     * @return An URI string if a mapping is found, or null otherwise.
+     * @return a URI string if a mapping is found, or null otherwise.
      */
     public String matchPublic(String publicId) {
         /*
@@ -329,7 +327,7 @@
      *
      * @param uri The URI reference of a resource.
      *
-     * @return An URI string if a mapping is found, or null otherwise.
+     * @return a URI string if a mapping is found, or null otherwise.
      */
     public String matchURI(String uri) {
         String match = null;
@@ -455,7 +453,7 @@
             delegateCatalog = getLoadedCatalog(catalogId);
             if (delegateCatalog == null) {
                 if (verifyCatalogFile(catalogURI)) {
-                    delegateCatalog = new CatalogImpl(catalog, features, catalogId);
+                    delegateCatalog = new CatalogImpl(catalog, features, catalogURI);
                     delegateCatalog.load();
                     delegateCatalogs.put(catalogId, delegateCatalog);
                 }
@@ -504,7 +502,8 @@
         }
 
         //Ignore it if it doesn't exist
-        if (!Files.exists(Paths.get(catalogURI))) {
+        if (Util.isFileUri(catalogURI) &&
+                !Util.isFileUriExist(catalogURI, false)) {
             return false;
         }
 
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 import java.net.URL;
 
 /**
- * Represents an uriEntry entry.
+ * Represents a uri entry.
  *
  * @since 9
  */
@@ -36,7 +36,7 @@
     URL uri;
 
     /**
-     * Construct a group entry.
+     * Construct a uri entry.
      * @param name The name attribute.
      * @param uri The uri attribute.
      */
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * 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,13 +25,20 @@
 package javax.xml.catalog;
 
 import java.io.File;
+import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Iterator;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import static javax.xml.catalog.CatalogFeatures.DEFER_FALSE;
+import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
+import javax.xml.catalog.CatalogFeatures.Feature;
+import static javax.xml.catalog.CatalogFeatures.PREFER_PUBLIC;
+import static javax.xml.catalog.CatalogFeatures.PREFER_SYSTEM;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_CONTINUE;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_IGNORE;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_STRICT;
 import jdk.xml.internal.SecuritySupport;
 
 /**
@@ -39,22 +46,25 @@
  * @since 9
  */
 class Util {
+
     final static String URN = "urn:publicid:";
     final static String PUBLICID_PREFIX = "-//";
     final static String PUBLICID_PREFIX_ALT = "+//";
+    final static String SCHEME_FILE = "file";
+    final static String SCHEME_JAR = "jar";
+    final static String SCHEME_JARFILE = "jar:file:";
 
     /**
      * Finds an entry in the catalog that matches with the publicId or systemId.
      *
-     * The resolution follows the following rules determined by the prefer setting:
+     * The resolution follows the following rules determined by the prefer
+     * setting:
      *
-     * prefer "system": attempts to resolve with a system entry;
-     *                  attempts to resolve with a public entry when only
-     *                  publicId is specified.
+     * prefer "system": attempts to resolve with a system entry; attempts to
+     * resolve with a public entry when only publicId is specified.
      *
-     * prefer "public": attempts to resolve with a system entry;
-     *                  attempts to resolve with a public entry if no matching
-     *                  system entry is found.
+     * prefer "public": attempts to resolve with a system entry; attempts to
+     * resolve with a public entry if no matching system entry is found.
      *
      * If no match is found, continue searching uri entries
      *
@@ -70,9 +80,9 @@
         catalog.reset();
         if (systemId != null) {
             /*
-               If a system identifier is specified, it is used no matter how
-            prefer is set.
-            */
+             If a system identifier is specified, it is used no matter how
+             prefer is set.
+             */
             resolvedSystemId = catalog.matchSystem(systemId);
         }
 
@@ -91,7 +101,7 @@
         if (resolvedSystemId == null) {
             Iterator<Catalog> iter = catalog.catalogs().iterator();
             while (iter.hasNext()) {
-                resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
+                resolvedSystemId = resolve((CatalogImpl) iter.next(), publicId, systemId);
                 if (resolvedSystemId != null) {
                     break;
                 }
@@ -102,73 +112,112 @@
         return resolvedSystemId;
     }
 
+    static void validateUrisSyntax(URI... uris) {
+        for (URI uri : uris) {
+            validateUriSyntax(uri);
+        }
+    }
+
+    static void validateUrisSyntax(String... uris) {
+        for (String uri : uris) {
+            validateUriSyntax(URI.create(uri));
+        }
+    }
+
     /**
-     * Resolves the specified file path to an absolute systemId. If it is
-     * relative, it shall be resolved using the base or user.dir property if
-     * base is not specified.
+     * Validate that the URI must be absolute and a valid URL.
      *
-     * @param file The specified file path
-     * @param baseURI the base URI
-     * @return The URI
-     * @throws CatalogException if the specified file path can not be converted
-     * to a system id
+     * Note that this method does not verify the existence of the resource. The
+     * Catalog standard requires that such resources be ignored.
+     *
+     * @param uri
+     * @throws IllegalArgumentException if the uri is not absolute and a valid
+     * URL
      */
-    static URI verifyAndGetURI(String file, URL baseURI)
-            throws MalformedURLException, URISyntaxException, IllegalArgumentException {
-        URL filepath;
-        URI temp;
-        if (file != null && file.length() > 0) {
-            File f = new File(file);
+    static void validateUriSyntax(URI uri) {
+        CatalogMessages.reportNPEOnNull("URI input", uri);
+
+        if (!uri.isAbsolute()) {
+            CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTABSOLUTE,
+                    new Object[]{uri}, null);
+        }
 
-            if (baseURI != null && !f.isAbsolute()) {
-                filepath = new URL(baseURI, fixSlashes(file));
-                temp = filepath.toURI();
-            } else {
-                temp = resolveURI(file);
-            }
-            //Paths.get may throw IllegalArgumentException
-            Path path = Paths.get(temp);
-            if (path.toFile().isFile()) {
-                return temp;
+        try {
+            // check if the scheme was valid
+            uri.toURL();
+        } catch (MalformedURLException ex) {
+            CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
+                    new Object[]{uri}, null);
+        }
+
+        // verify the resource exists where possible
+        if (isFileUri(uri)) {
+            if (!isFileUriExist(uri, false)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
+                        new Object[]{uri}, null);
             }
         }
-        return null;
     }
 
     /**
-     * Resolves the specified uri. If the uri is relative, makes it absolute by
-     * the user.dir directory.
+     * Checks whether the URI is a file URI, including JAR file.
      *
-     * @param uri The specified URI.
-     * @return The resolved URI
+     * @param uri the specified URI.
+     * @return true if it is a file or JAR file URI, false otherwise
      */
-    static URI resolveURI(String uri) throws MalformedURLException {
-        if (uri == null) {
-            uri = "";
+    static boolean isFileUri(URI uri) {
+        if (SCHEME_FILE.equals(uri.getScheme())
+                || SCHEME_JAR.equals(uri.getScheme())) {
+            return true;
         }
-
-        URI temp = null;
-        try {
-            URL url = new URL(uri);
-            temp = url.toURI();
-        } catch (MalformedURLException | URISyntaxException mue) {
-            File file = new File(uri);
-            temp = file.toURI();
-        }
-
-        return temp;
+        return false;
     }
 
     /**
-     * Replace backslashes with forward slashes. (URLs always use forward
-     * slashes.)
+     * Verifies whether the file resource exists.
      *
-     * @param sysid The input system identifier.
-     * @return The same system identifier with backslashes turned into forward
-     * slashes.
+     * @param uri the URI to locate the resource
+     * @param openJarFile a flag to indicate whether a JAR file should be
+     * opened. This operation may be expensive.
+     * @return true if the resource exists, false otherwise.
      */
-    static String fixSlashes(String sysid) {
-        return sysid.replace('\\', '/');
+    static boolean isFileUriExist(URI uri, boolean openJarFile) {
+        if (uri != null && uri.isAbsolute()) {
+            if (null != uri.getScheme()) {
+                switch (uri.getScheme()) {
+                    case SCHEME_FILE:
+                        String path = uri.getPath();
+                        File f1 = new File(path);
+                        if (f1.isFile()) {
+                            return true;
+                        }
+                        break;
+                    case SCHEME_JAR:
+                        String tempUri = uri.toString();
+                        int pos = tempUri.indexOf("!");
+                        if (pos < 0) {
+                            return false;
+                        }
+                        if (openJarFile) {
+                            String jarFile = tempUri.substring(SCHEME_JARFILE.length(), pos);
+                            String entryName = tempUri.substring(pos + 2);
+                            try {
+                                JarFile jf = new JarFile(jarFile);
+                                JarEntry je = jf.getJarEntry(entryName);
+                                if (je != null) {
+                                    return true;
+                                }
+                            } catch (IOException ex) {
+                                return false;
+                            }
+                        } else {
+                            return true;
+                        }
+                        break;
+                }
+            }
+        }
+        return false;
     }
 
     /**
@@ -187,11 +236,12 @@
     }
 
     /**
-     * Checks whether the specified string is null or empty, returns the original
-     * string with leading and trailing spaces removed if not.
+     * Checks whether the specified string is null or empty, returns the
+     * original string with leading and trailing spaces removed if not.
+     *
      * @param test the string to be tested
-     * @return the original string with leading and trailing spaces removed,
-     * or null if it is null or empty
+     * @return the original string with leading and trailing spaces removed, or
+     * null if it is null or empty
      *
      */
     static String getNotNullOrEmpty(String test) {
@@ -206,4 +256,39 @@
             }
         }
     }
+
+    /**
+     * Validates the input for features.
+     *
+     * @param f the feature
+     * @param value the value
+     * @throws IllegalArgumentException if the value is invalid for the feature
+     */
+    static void validateFeatureInput(Feature f, String value) {
+        CatalogMessages.reportNPEOnNull(f.name(), value);
+        if (value.length() == 0) {
+            CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                    new Object[]{value, f.name()}, null);
+        }
+
+        if (f == Feature.PREFER) {
+            if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                        new Object[]{value, Feature.PREFER.name()}, null);
+            }
+        } else if (f == Feature.DEFER) {
+            if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                        new Object[]{value, Feature.DEFER.name()}, null);
+            }
+        } else if (f == Feature.RESOLVE) {
+            if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
+                    && !value.equals(RESOLVE_IGNORE)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                        new Object[]{value, Feature.RESOLVE.name()}, null);
+            }
+        } else if (f == Feature.FILES) {
+            Util.validateUrisSyntax(value.split(";"));
+        }
+    }
 }
--- a/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@
     @Test
     public void specifyCatalogViaSysProps() {
         setSystemProperty(FEATURE_FILES,
-                getCatalogPath("specifyCatalog-sysProps.xml"));
+                getCatalogPath("specifyCatalog-sysProps.xml").toASCIIString());
 
         checkResolutionOnEntityResolver(catalogResolver((String[]) null),
                 "http://local/base/dtd/docSysPropsSys.dtd");
@@ -107,6 +107,6 @@
     }
 
     private static CatalogFeatures createFeature(String catalogName) {
-        return builder().with(FILES, getCatalogPath(catalogName)).build();
+        return builder().with(FILES, getCatalogPath(catalogName).toASCIIString()).build();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/dummy.xml	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,1 @@
+<dummy />
--- a/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * 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,17 +25,16 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogManager;
 import javax.xml.catalog.CatalogResolver;
-
 import jaxp.library.JAXPTestUtilities;
 
 /*
@@ -115,20 +114,20 @@
     }
 
     // Gets the paths of the specified catalogs.
-    private static String[] getCatalogPaths(String... catalogNames) {
+    private static URI[] getCatalogPaths(String... catalogNames) {
         return catalogNames == null
                 ? null
                 : Stream.of(catalogNames).map(
                         catalogName -> getCatalogPath(catalogName)).collect(
-                                Collectors.toList()).toArray(new String[0]);
+                                Collectors.toList()).toArray(new URI[0]);
     }
 
     // Gets the paths of the specified catalogs.
-    static String getCatalogPath(String catalogName) {
+    static URI getCatalogPath(String catalogName) {
         return catalogName == null
                 ? null
-                : JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles")
-                        + catalogName;
+                : Paths.get(JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles")
+                        + catalogName).toUri();
     }
 
     /* ********** jaxp.properties ********** */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JarUtils.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jaxp.library;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class consists exclusively of static utility methods that are useful
+ * for creating and manipulating JAR files.
+ */
+
+public final class JarUtils {
+    private JarUtils() { }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file)
+        throws IOException
+    {
+        // create the target directory
+        Path parent = jarfile.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+
+        List<Path> entries = new ArrayList<>();
+        for (Path entry : file) {
+            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
+                        (p, attrs) -> attrs.isRegularFile())
+                    .map(e -> dir.relativize(e))
+                    .forEach(entries::add);
+        }
+
+        try (OutputStream out = Files.newOutputStream(jarfile);
+             JarOutputStream jos = new JarOutputStream(out))
+        {
+            if (man != null) {
+                JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+                jos.putNextEntry(je);
+                man.write(jos);
+                jos.closeEntry();
+            }
+
+            for (Path entry : entries) {
+                String name = toJarEntryName(entry);
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+                jos.closeEntry();
+            }
+        }
+    }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile>  -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, Path... file)
+        throws IOException
+    {
+        createJarFile(jarfile, null, dir, file);
+    }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, String... input)
+        throws IOException
+    {
+        Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
+        createJarFile(jarfile, dir, paths);
+    }
+
+    /**
+     * Creates a JAR file from the contents of a directory.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> .}
+     */
+    public static void createJarFile(Path jarfile, Path dir) throws IOException {
+        createJarFile(jarfile, dir, Paths.get("."));
+    }
+
+    /**
+     * Map a file path to the equivalent name in a JAR file
+     */
+    private static String toJarEntryName(Path file) {
+        Path normalized = file.normalize();
+        return normalized.subpath(0, normalized.getNameCount())  // drop root
+                .toString()
+                .replace(File.separatorChar, '/');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/SimpleHttpServer.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jaxp.library;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * A simple HTTP Server
+ */
+public class SimpleHttpServer {
+    HttpServer _httpserver;
+    ExecutorService _executor;
+
+    String _address;
+
+    String _context, _docroot;
+    int _port;
+
+    public SimpleHttpServer(String context, String docroot) {
+        //let the system pick up an ephemeral port in a bind operation
+        this(0, context, docroot);
+    }
+
+    public SimpleHttpServer(int port, String context, String docroot) {
+        _port = port;
+        _context = context;
+        _docroot = docroot;
+    }
+
+    public void start() {
+        MyHttpHandler handler = new MyHttpHandler(_docroot);
+        InetSocketAddress addr = new InetSocketAddress(_port);
+        try {
+            _httpserver = HttpServer.create(addr, 0);
+        } catch (IOException ex) {
+            throw new RuntimeException("cannot create httpserver", ex);
+        }
+
+        //TestHandler is mapped to /test
+        HttpContext ctx = _httpserver.createContext(_context, handler);
+
+        _executor = Executors.newCachedThreadPool();
+        _httpserver.setExecutor(_executor);
+        _httpserver.start();
+
+        _address = "http://localhost:" + _httpserver.getAddress().getPort();
+    }
+
+    public void stop() {
+        _httpserver.stop(2);
+        _executor.shutdown();
+    }
+
+    public String getAddress() {
+        return _address;
+    }
+
+    static class MyHttpHandler implements HttpHandler {
+
+        String _docroot;
+
+        public MyHttpHandler(String docroot) {
+            _docroot = docroot;
+        }
+
+        public void handle(HttpExchange t)
+                throws IOException {
+            InputStream is = t.getRequestBody();
+            Headers map = t.getRequestHeaders();
+            Headers rmap = t.getResponseHeaders();
+            OutputStream os = t.getResponseBody();
+            URI uri = t.getRequestURI();
+            String path = uri.getPath();
+
+
+            while (is.read() != -1) ;
+            is.close();
+
+            File f = new File(_docroot, path);
+            if (!f.exists()) {
+                notfound(t, path);
+                return;
+            }
+
+            String method = t.getRequestMethod();
+            if (method.equals("HEAD")) {
+                rmap.set("Content-Length", Long.toString(f.length()));
+                t.sendResponseHeaders(200, -1);
+                t.close();
+            } else if (!method.equals("GET")) {
+                t.sendResponseHeaders(405, -1);
+                t.close();
+                return;
+            }
+
+            if (path.endsWith(".html") || path.endsWith(".htm")) {
+                rmap.set("Content-Type", "text/html");
+            } else {
+                rmap.set("Content-Type", "text/plain");
+            }
+
+            t.sendResponseHeaders (200, f.length());
+
+            FileInputStream fis = new FileInputStream(f);
+            int count = 0;
+            try {
+                byte[] buf = new byte[16 * 1024];
+                int len;
+                while ((len = fis.read(buf)) != -1) {
+                    os.write(buf, 0, len);
+                    count += len;
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            fis.close();
+            os.close();
+        }
+
+        void moved(HttpExchange t) throws IOException {
+            Headers req = t.getRequestHeaders();
+            Headers map = t.getResponseHeaders();
+            URI uri = t.getRequestURI();
+            String host = req.getFirst("Host");
+            String location = "http://" + host + uri.getPath() + "/";
+            map.set("Content-Type", "text/html");
+            map.set("Location", location);
+            t.sendResponseHeaders(301, -1);
+            t.close();
+        }
+
+        void notfound(HttpExchange t, String p) throws IOException {
+            t.getResponseHeaders().set("Content-Type", "text/html");
+            t.sendResponseHeaders(404, 0);
+            OutputStream os = t.getResponseBody();
+            String s = "<h2>File not found</h2>";
+            s = s + p + "<p>";
+            os.write(s.getBytes());
+            os.close();
+            t.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogAccessTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package catalog;
+
+import java.net.URI;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+import static jaxp.library.JAXPTestUtilities.tryRunWithAllPerm;
+
+/*
+ * @test
+ * @bug 8171243
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm -DrunSecMngr=true catalog.CatalogAccessTest
+ * @summary the Catalog API grants no privilege to external resources. This test
+ * verifies that SecurityException will be thrown if access to resources is denied
+ * by the security manager.
+ */
+@Listeners({jaxp.library.BasePolicy.class})
+public class CatalogAccessTest {
+    static final CatalogFeatures FEATURES = CatalogFeatures.builder().
+            with(CatalogFeatures.Feature.PREFER, "system").build();
+
+    /*
+     * Verifies that the SecurityException is thrown if access to the resource is
+     * denied by the security manager.
+     */
+    @Test(dataProvider = "accessTest", expectedExceptions = SecurityException.class)
+    public void testSecurity(String cfile, String sysId, String pubId) throws Exception {
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(cfile));
+        InputSource is = cr.resolveEntity(pubId, sysId);
+        Assert.fail("Failed to throw SecurityException");
+    }
+
+    /*
+        DataProvider: used for SecurityException testing
+        Data columns:
+        catalog uri, systemId, publicId
+     */
+    @DataProvider(name = "accessTest")
+    Object[][] getDataForAccessTest() throws Exception {
+        String systemId = "http://www.sys00test.com/rewrite.dtd";
+        String publicId = "PUB-404";
+        String urlFile = tryRunWithAllPerm(() ->
+                getClass().getResource("rewriteSystem_id.xml").toExternalForm());
+        return new Object[][]{
+            {urlFile, systemId, publicId}
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package catalog;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import static java.nio.file.StandardOpenOption.APPEND;
+import static java.nio.file.StandardOpenOption.CREATE;
+import javax.xml.catalog.Catalog;
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import static jaxp.library.JAXPTestUtilities.getSystemProperty;
+import jaxp.library.JarUtils;
+import jaxp.library.SimpleHttpServer;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+/*
+ * @test
+ * @bug 8151154 8171243
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm catalog.CatalogFileInputTest
+ * @summary Verifies that the Catalog API accepts valid URIs only;
+            Verifies that the CatalogFeatures' builder throws
+ *          IllegalArgumentException on invalid file inputs.
+ *          This test was splitted from CatalogTest.java due to
+ *          JDK-8168968, it has to only run without SecurityManager
+ *          because an ACE will be thrown for invalid path.
+ */
+@Listeners({jaxp.library.FilePolicy.class, jaxp.library.NetAccessPolicy.class})
+public class CatalogFileInputTest extends CatalogSupportBase {
+
+    static final CatalogFeatures FEATURES = CatalogFeatures.builder().
+            with(CatalogFeatures.Feature.PREFER, "system").build();
+    static String USER_DIR = getSystemProperty("user.dir");
+    static String CLS_DIR = getSystemProperty("test.classes");
+    static String SRC_DIR = System.getProperty("test.src");
+    static String JAR_CONTENT = "META-INF";
+    final static String SCHEME_JARFILE = "jar:";
+    static final String REMOTE_FILE_LOCATION = "/jar/META-INF";
+    static final String DOCROOT = SRC_DIR;
+    static final String TESTCONTEXT = REMOTE_FILE_LOCATION;  //mapped to local file path
+    SimpleHttpServer _httpserver;
+    String _remoteFilePath;
+
+    /*
+     * Initializing fields
+     */
+    @BeforeClass
+    public void setUpClass() throws Exception {
+        super.setUp();
+
+        // set up HttpServer
+        _httpserver = new SimpleHttpServer(TESTCONTEXT, DOCROOT);
+        _httpserver.start();
+        _remoteFilePath = _httpserver.getAddress() + REMOTE_FILE_LOCATION;
+
+    }
+
+    @AfterClass
+    protected void tearDown() throws Exception {
+        if (_httpserver != null) {
+            _httpserver.stop();
+        }
+    }
+
+    /*
+     * Verifies that the Catalog can be created with file system paths including JAR
+     * and http URL, and used to resolve a systemId as expected.
+     */
+    @Test(dataProvider = "acceptedURI")
+    public void testMatch(String uri, String sysId, String pubId,
+            String expectedId, String msg) throws Exception {
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(uri));
+        InputSource is = cr.resolveEntity(pubId, sysId);
+        Assert.assertNotNull(is, msg);
+        Assert.assertEquals(expectedId, is.getSystemId(), msg);
+    }
+
+    @Test(dataProvider = "invalidCatalog")
+    public void testEmptyCatalog(String uri, String publicId, String msg) {
+        Catalog c = CatalogManager.catalog(FEATURES, uri != null? URI.create(uri) : null);
+        Assert.assertNull(c.matchSystem(publicId), msg);
+    }
+
+    @Test(dataProvider = "invalidCatalog", expectedExceptions = CatalogException.class)
+    public void testCatalogResolverWEmptyCatalog(String uri, String publicId, String msg) {
+        CatalogResolver cr = CatalogManager.catalogResolver(
+                CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "strict").build(),
+                uri != null? URI.create(uri) : null);
+        InputSource is = cr.resolveEntity(publicId, "");
+    }
+
+    @Test(dataProvider = "invalidCatalog")
+    public void testCatalogResolverWEmptyCatalog1(String uri, String publicId, String msg) {
+        CatalogResolver cr = CatalogManager.catalogResolver(
+                CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "continue").build(),
+                uri != null? URI.create(uri) : null);
+        Assert.assertNull(cr.resolveEntity(publicId, ""), msg);
+    }
+
+    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+    public void testFileInput(String file) {
+        CatalogFeatures features = CatalogFeatures.builder()
+            .with(CatalogFeatures.Feature.FILES, file)
+            .build();
+    }
+
+    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+    public void testInvalidUri(String file) {
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, file != null? URI.create(file) : null);
+    }
+
+    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+    public void testInvalidUri1(String file) {
+        Catalog c = CatalogManager.catalog(FEATURES, file != null? URI.create(file) : null);
+        System.err.println("Catalog =" + c);
+    }
+
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullFileInput() {
+        CatalogFeatures features = CatalogFeatures.builder()
+            .with(CatalogFeatures.Feature.FILES, null)
+            .build();
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullUri() {
+        URI uri = null;
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, uri);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullUri1() {
+        URI uri = null;
+        Catalog c = CatalogManager.catalog(FEATURES, uri);
+    }
+
+    String systemId = "http://www.sys00test.com/rewrite.dtd";
+    String publicId = "PUB-404";
+    String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd";
+    String errMsg = "Relative rewriteSystem with xml:base at group level failed";
+
+    /*
+        DataProvider: used to verify CatalogResolver's resolveEntity function.
+        Data columns:
+        catalog, systemId, publicId, expectedUri, msg
+     */
+    @DataProvider(name = "acceptedURI")
+    Object[][] getData() throws Exception {
+        String filename = "rewriteSystem_id.xml";
+        String urlFile = getClass().getResource(filename).toExternalForm();
+        String urlHttp = _remoteFilePath + "/jax-ws-catalog.xml";
+        String remoteXSD = _remoteFilePath + "/catalog/ws-addr.xsd";
+        File file = new File(CLS_DIR + "/JDK8171243.jar!/META-INF/jax-ws-catalog.xml");
+        String jarPath = SCHEME_JARFILE + file.toURI().toString();
+        String xsd = jarPath.substring(0, jarPath.lastIndexOf("/")) + "/catalog/ws-addr.xsd";
+
+        // create JAR file
+        try {
+            JarUtils.createJarFile(Paths.get(CLS_DIR + "/JDK8171243.jar"),
+                    Paths.get(SRC_DIR + "/jar"), JAR_CONTENT);
+        } catch (IOException ex) {
+            Assert.fail("Failed to create JAR: " + ex.getMessage());
+        }
+
+        return new Object[][]{
+            // URL
+            {urlFile, systemId, publicId, expected, errMsg},
+            {urlHttp, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", remoteXSD, "http test failed."},
+            // JAR file
+            {jarPath, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", xsd, "jar file test failed."},
+        };
+    }
+
+    /*
+     *  DataProvider: invalid catalog result in empty catalog
+     *  Note: the difference from invalidInput is that invalidInput is syntactically
+     *  rejected with an IAE.
+     */
+    @DataProvider(name = "invalidCatalog")
+    public Object[][] getInvalidCatalog() throws Exception {
+        String catalogUri = getClass().getResource("catalog_invalid.xml").toExternalForm();
+        return new Object[][]{
+            {catalogUri, "-//W3C//DTD XHTML 1.0 Strict//EN",
+                "The catalog is invalid, attempting to match the public entry shall return null."}
+        };
+    }
+
+    /*
+     *  DataProvider: a list of invalid inputs, expects IAE
+     *  Note: exclude null since NPE would have been expected
+     */
+    @DataProvider(name = "invalidInput")
+    public Object[][] getFiles() throws Exception {
+        String filename = "rewriteSystem_id.xml";
+        copyFile(Paths.get(SRC_DIR + "/" + filename), Paths.get(filename));
+        String absolutePath = getClass().getResource(filename).getFile();
+
+        return new Object[][]{
+            {""},
+            {"file:a/b\\c"},
+            {"file:/../../.."},
+            {"c:/te:t"},
+            {"c:/te?t"},
+            {"c/te*t"},
+            {"in|valid.txt"},
+            {"shema:invalid.txt"},
+            // relative file path
+            {filename},
+            // absolute file path
+            {absolutePath}
+        };
+    }
+
+    /*
+       DataProvider: a list of invalid inputs
+     */
+    @DataProvider(name = "nullTest")
+    public Object[][] getNull() throws Exception {
+
+        return new Object[][]{
+            {null},
+        };
+    }
+
+    void copyFile(Path src, Path target) throws Exception {
+
+        try (InputStream in = Files.newInputStream(src);
+                BufferedReader reader
+                = new BufferedReader(new InputStreamReader(in));
+                OutputStream out = new BufferedOutputStream(
+                        Files.newOutputStream(target, CREATE, APPEND));
+                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out))) {
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                bw.write(line);
+            }
+        } catch (IOException x) {
+            throw new Exception(x.getMessage());
+        }
+    }
+}
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +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.
- *
- * This code is distributed in the hope that it 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 catalog;
-
-import javax.xml.catalog.CatalogFeatures;
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/*
- * @test
- * @bug 8151154
- * @run testng/othervm catalog.CatalogInvalidPathTest
- * @summary Verifies that the CatalogFeatures' builder throws
- *          IllegalArgumentException on invalid file inputs.
- *          This test was splitted from CatalogTest.java due to
- *          JDK-8168968, it has to only run without SecurityManager
- *          because an ACE will be thrown for invalid path.
- */
-public class CatalogInvalidPathTest {
-    /*
-       DataProvider: for testing the verification of file paths by
-                     the CatalogFeatures builder
-     */
-    @DataProvider(name = "invalidPaths")
-    public Object[][] getFiles() {
-        return new Object[][]{
-            {null},
-            {""},
-            {"file:a/b\\c"},
-            {"file:/../../.."},
-            {"c:/te:t"},
-            {"c:/te?t"},
-            {"c/te*t"},
-            {"in|valid.txt"},
-            {"shema:invalid.txt"},
-        };
-    }
-
-    @Test(dataProvider = "invalidPaths", expectedExceptions = IllegalArgumentException.class)
-    public void testFileInput(String file) {
-        CatalogFeatures features = CatalogFeatures.builder()
-            .with(CatalogFeatures.Feature.FILES, file)
-            .build();
-    }
-}
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,13 @@
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
 import javax.xml.XMLConstants;
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogResolver;
@@ -133,8 +140,8 @@
         dtd_system = filepath + "system.dtd";
         dtd_systemResolved = "<!ENTITY system \"resolved by an EntityHandler, rather than a Catalog\">";
 
-        xml_catalog = filepath + "CatalogSupport.xml";
-        xml_bogus_catalog = filepath + "CatalogSupport_bogus.xml";
+        xml_catalog = Paths.get(filepath + "CatalogSupport.xml").toUri().toASCIIString();
+        xml_bogus_catalog = Paths.get(filepath + "CatalogSupport_bogus.xml").toUri().toASCIIString();
 
         xml_xInclude = "<?xml version=\"1.0\"?>\n" +
             "<xinclude:include xmlns:xinclude=\"http://www.w3.org/2001/XInclude\"\n" +
@@ -997,4 +1004,35 @@
             return null;
         }
     }
+
+    /**
+     * Simple policy implementation that grants a set of permissions to all code
+     * sources and protection domains.
+     */
+    static class SimplePolicy extends Policy {
+
+        private final Permissions perms;
+
+        public SimplePolicy(Permission... permissions) {
+            perms = new Permissions();
+            for (Permission permission : permissions) {
+                perms.add(permission);
+            }
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource cs) {
+            return perms;
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain pd) {
+            return perms;
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain pd, Permission p) {
+            return perms.implies(p);
+        }
+    }
 }
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,17 +22,14 @@
  */
 package catalog;
 
-import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
-import static jaxp.library.JAXPTestUtilities.setSystemProperty;
-
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.net.URI;
 import java.nio.file.Paths;
-
 import javax.xml.XMLConstants;
 import javax.xml.catalog.Catalog;
 import javax.xml.catalog.CatalogException;
@@ -55,7 +52,8 @@
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
-
+import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
+import static jaxp.library.JAXPTestUtilities.setSystemProperty;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
@@ -95,10 +93,10 @@
      * CatalogException is thrown.
      */
     @Test(dataProvider = "getFeatures", expectedExceptions = CatalogException.class)
-    public void testCircularRef(CatalogFeatures cf, String xml) {
+    public void testCircularRef(CatalogFeatures cf, String xml) throws Exception {
         CatalogResolver catalogResolver = CatalogManager.catalogResolver(
                 cf,
-                getClass().getResource(xml).getFile());
+                getClass().getResource(xml).toURI());
         catalogResolver.resolve("anyuri", "");
     }
 
@@ -108,14 +106,14 @@
      */
     @DataProvider(name = "getFeatures")
     public Object[][] getFeatures() {
-
+        String self = "catalogReferCircle-itself.xml";
+        String left = "catalogReferCircle-left.xml";
         return new Object[][]{
-            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(),
-                "catalogReferCircle-itself.xml"},
-            {CatalogFeatures.defaults(), "catalogReferCircle-itself.xml"},
-            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(),
-                "catalogReferCircle-left.xml"},
-            {CatalogFeatures.defaults(), "catalogReferCircle-left.xml"},};
+            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(), self},
+            {CatalogFeatures.defaults(), self},
+            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(), left},
+            {CatalogFeatures.defaults(), left}
+        };
     }
 
     /*
@@ -134,7 +132,7 @@
      * Expected: the parser returns the expected string.
     */
     @Test(dataProvider = "supportXMLResolver")
-    public void supportEntityResolver(String catalogFile, String xml, String expected) throws Exception {
+    public void supportEntityResolver(URI catalogFile, String xml, String expected) throws Exception {
         String xmlSource = getClass().getResource(xml).getFile();
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
@@ -150,7 +148,7 @@
      * Expected: the parser returns the expected string.
     */
     @Test(dataProvider = "supportXMLResolver")
-    public void supportXMLResolver(String catalogFile, String xml, String expected) throws Exception {
+    public void supportXMLResolver(URI catalogFile, String xml, String expected) throws Exception {
         String xmlSource = getClass().getResource(xml).getFile();
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
@@ -159,7 +157,7 @@
         xifactory.setProperty(XMLInputFactory.IS_COALESCING, true);
         xifactory.setProperty(XMLInputFactory.RESOLVER, cr);
         File file = new File(xmlSource);
-        String systemId = file.toURI().toString();
+        String systemId = file.toURI().toASCIIString();
         InputStream entityxml = new FileInputStream(file);
         XMLStreamReader streamReader = xifactory.createXMLStreamReader(systemId, entityxml);
         String result = null;
@@ -183,7 +181,7 @@
      * Fail: throws Exception if references are not resolved (by the CatalogResolver)
     */
     @Test(dataProvider = "supportLSResourceResolver")
-    public void supportLSResourceResolver(String catalogFile, Source schemaSource) throws SAXException {
+    public void supportLSResourceResolver(URI catalogFile, Source schemaSource) throws SAXException {
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
 
@@ -199,7 +197,7 @@
      * Fail: throws Exception if references are not resolved (by the CatalogResolver)
     */
     @Test(dataProvider = "supportLSResourceResolver1")
-    public void supportLSResourceResolver1(String catalogFile, Source source) throws Exception {
+    public void supportLSResourceResolver1(URI catalogFile, Source source) throws Exception {
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
 
@@ -215,7 +213,7 @@
      * Fail: throws Exception if references are not resolved (by the CatalogResolver)
     */
     @Test(dataProvider = "supportURIResolver")
-    public void supportURIResolver(String catalogFile, Source xsl, Source xml, String expected) throws Exception {
+    public void supportURIResolver(URI catalogFile, Source xsl, Source xml, String expected) throws Exception {
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
 
@@ -235,9 +233,9 @@
         catalog filepath, xml source file, expected result
      */
     @DataProvider(name = "supportXMLResolver")
-    public Object[][] supportXMLResolver() {
-        String catalogFile = getClass().getResource("catalog.xml").getFile();
-        String catalogFileUri = getClass().getResource("catalog_uri.xml").getFile();
+    public Object[][] supportXMLResolver() throws Exception {
+        URI catalogFile = getClass().getResource("catalog.xml").toURI();
+        URI catalogFileUri = getClass().getResource("catalog_uri.xml").toURI();
 
         return new Object[][]{
             {catalogFile, "system.xml", "Test system entry"},
@@ -263,9 +261,9 @@
         catalog filepath, schema source file
      */
     @DataProvider(name = "supportLSResourceResolver")
-    public Object[][] supportLSResourceResolver() {
-        String catalogFile = getClass().getResource("CatalogSupport.xml").getFile();
-        String catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").getFile();
+    public Object[][] supportLSResourceResolver() throws Exception {
+        URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI();
+        URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI();
 
         /*
          * XMLSchema.xsd has a reference to XMLSchema.dtd which in turn refers to
@@ -287,9 +285,9 @@
         catalog filepath, source file
      */
     @DataProvider(name = "supportLSResourceResolver1")
-    public Object[][] supportLSResourceResolver1() {
-        String catalogFile = getClass().getResource("CatalogSupport.xml").getFile();
-        String catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").getFile();
+    public Object[][] supportLSResourceResolver1() throws Exception {
+        URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI();
+        URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI();
 
         /*
          * val_test.xml has a reference to system.dtd and val_test.xsd
@@ -310,9 +308,9 @@
         catalog filepath, xsl source, xml source file
      */
     @DataProvider(name = "supportURIResolver")
-    public Object[][] supportURIResolver() {
-        String catalogFile = getClass().getResource("CatalogSupport.xml").getFile();
-        String catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").getFile();
+    public Object[][] supportURIResolver() throws Exception {
+        URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI();
+        URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI();
         SAXSource xslSource = new SAXSource(new InputSource(new File(xsl_doc).toURI().toASCIIString()));
 
         /*
@@ -353,8 +351,9 @@
      * other cases in that test.
      */
     @Test(dataProvider = "resolveUri")
-    public void testMatch1(String cFile, String href, String expectedFile, String expectedUri, String msg) {
-        String catalogFile = getClass().getResource(cFile).getFile();
+    public void testMatch1(String cFile, String href, String expectedFile,
+            String expectedUri, String msg) throws Exception {
+        URI catalogFile = getClass().getResource(cFile).toURI();
         CatalogResolver cur = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
         Source source = cur.resolve(href, null);
         Assert.assertNotNull(source, "Source returned is null");
@@ -368,15 +367,16 @@
      */
     @Test(dataProvider = "hierarchyOfCatFilesData")
     public void hierarchyOfCatFiles2(String systemId, String expectedUri) {
-        String file1 = getClass().getResource("first_cat.xml").getFile();
-        String file2 = getClass().getResource("second_cat.xml").getFile();
+        String file1 = getClass().getResource("first_cat.xml").toExternalForm();
+        String file2 = getClass().getResource("second_cat.xml").toExternalForm();
         String files = file1 + ";" + file2;
 
         try {
             setSystemProperty(KEY_FILES, files);
             CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults());
             String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId();
-            Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), "System ID match not right");
+            Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"),
+                    "System ID match not right");
         } finally {
             clearSystemProperty(KEY_FILES);
         }
@@ -390,8 +390,9 @@
      * expected.
      */
     @Test(dataProvider = "resolveEntity")
-    public void testMatch1(String cfile, String prefer, String sysId, String pubId, String expectedUri, String expectedFile, String msg) {
-        String catalogFile = getClass().getResource(cfile).getFile();
+    public void testMatch1(String cfile, String prefer, String sysId, String pubId,
+            String expectedUri, String expectedFile, String msg) throws Exception {
+        URI catalogFile = getClass().getResource(cfile).toURI();
         CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build();
         CatalogResolver catalogResolver = CatalogManager.catalogResolver(features, catalogFile);
         InputSource is = catalogResolver.resolveEntity(pubId, sysId);
@@ -406,9 +407,12 @@
      * results as expected.
      */
     @Test(dataProvider = "matchWithPrefer")
-    public void matchWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) {
-        String catalogFile = getClass().getResource(cfile).getFile();
-        Catalog c = CatalogManager.catalog(CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(), catalogFile);
+    public void matchWithPrefer(String prefer, String cfile, String publicId,
+            String systemId, String expected) throws Exception {
+        URI catalogFile = getClass().getResource(cfile).toURI();
+        Catalog c = CatalogManager.catalog(
+                CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(),
+                catalogFile);
         String result;
         if (publicId != null && publicId.length() > 0) {
             result = c.matchPublic(publicId);
@@ -430,8 +434,9 @@
      *                  system entry is found.
      */
     @Test(dataProvider = "resolveWithPrefer")
-    public void resolveWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) {
-        String catalogFile = getClass().getResource(cfile).getFile();
+    public void resolveWithPrefer(String prefer, String cfile, String publicId,
+            String systemId, String expected) throws Exception {
+        URI catalogFile = getClass().getResource(cfile).toURI();
         CatalogFeatures f = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).with(CatalogFeatures.Feature.RESOLVE, "ignore").build();
         CatalogResolver catalogResolver = CatalogManager.catalogResolver(f, catalogFile);
         String result = catalogResolver.resolveEntity(publicId, systemId).getSystemId();
@@ -445,8 +450,8 @@
      * be loaded is determined by the defer attribute.
      */
     @Test(dataProvider = "invalidAltCatalogs", expectedExceptions = CatalogException.class)
-    public void testDeferAltCatalogs(String file) {
-        String catalogFile = getClass().getResource(file).getFile();
+    public void testDeferAltCatalogs(String file) throws Exception {
+        URI catalogFile = getClass().getResource(file).toURI();
         CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "true").build();
         /*
           Since the defer attribute is set to false in the specified catalog file,
@@ -462,8 +467,8 @@
      * PREFER from Features API taking precedence over catalog file
      */
     @Test
-    public void testJDK8146237() {
-        String catalogFile = getClass().getResource("JDK8146237_catalog.xml").getFile();
+    public void testJDK8146237() throws Exception {
+        URI catalogFile = getClass().getResource("JDK8146237_catalog.xml").toURI();
 
         try {
             CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, "system").build();
@@ -482,8 +487,8 @@
        Verifies that the resulting systemId does not contain duplicate slashes
     */
     @Test
-    public void testRewriteSystem() {
-        String catalog = getClass().getResource("rewriteCatalog.xml").getFile();
+    public void testRewriteSystem() throws Exception {
+        URI catalog = getClass().getResource("rewriteCatalog.xml").toURI();
 
         try {
             CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog);
@@ -500,8 +505,8 @@
        Verifies that the resulting systemId does not contain duplicate slashes
     */
     @Test
-    public void testRewriteUri() {
-        String catalog = getClass().getResource("rewriteCatalog.xml").getFile();
+    public void testRewriteUri() throws Exception {
+        URI catalog = getClass().getResource("rewriteCatalog.xml").toURI();
 
         try {
 
@@ -519,18 +524,18 @@
     */
     @Test(expectedExceptions = NullPointerException.class)
     public void testFeatureNull() {
-        CatalogResolver resolver = CatalogManager.catalogResolver(null, "");
+        CatalogResolver resolver = CatalogManager.catalogResolver(null, null);
 
     }
 
     /*
        @bug 8144966
-       Verifies that passing null as the path will result in a NPE.
+       Verifies that passing null as the URI will result in a NPE.
     */
     @Test(expectedExceptions = NullPointerException.class)
     public void testPathNull() {
-        String path = null;
-        CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), path);
+        URI uri = null;
+        CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), uri);
     }
 
     /*
@@ -540,10 +545,11 @@
     that matches the expected value.
      */
     @Test(dataProvider = "catalog")
-    public void testCatalogResolver(String test, String expected, String catalogFile, String xml, SAXParser saxParser) {
-        String catalog = null;
+    public void testCatalogResolver(String test, String expected, String catalogFile,
+            String xml, SAXParser saxParser) throws Exception {
+        URI catalog = null;
         if (catalogFile != null) {
-            catalog = getClass().getResource(catalogFile).getFile();
+            catalog = getClass().getResource(catalogFile).toURI();
         }
         String url = getClass().getResource(xml).getFile();
         try {
@@ -565,8 +571,8 @@
     catalog is provided, the resolver will throw an exception by default.
     */
     @Test
-    public void testInvalidCatalog() {
-        String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+    public void testInvalidCatalog() throws Exception {
+        URI catalog = getClass().getResource("catalog_invalid.xml").toURI();
 
         String test = "testInvalidCatalog";
         try {
@@ -590,7 +596,7 @@
     */
     @Test
     public void testIgnoreInvalidCatalog() {
-        String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+        String catalog = getClass().getResource("catalog_invalid.xml").toExternalForm();
         CatalogFeatures f = CatalogFeatures.builder()
                 .with(Feature.FILES, catalog)
                 .with(Feature.PREFER, "public")
@@ -600,7 +606,7 @@
 
         String test = "testInvalidCatalog";
         try {
-            CatalogResolver resolver = CatalogManager.catalogResolver(f, "");
+            CatalogResolver resolver = CatalogManager.catalogResolver(f);
             String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId();
             System.out.println("testIgnoreInvalidCatalog: expected [null]");
             System.out.println("testIgnoreInvalidCatalog: expected [null]");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/MANIFEST.MF	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Created-By: 9-ea (Oracle Corporation)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/catalog/ws-addr.xsd	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    W3C XML Schema defined in the Web Services Addressing 1.0 specification
+    http://www.w3.org/TR/ws-addr-core
+
+   Copyright © 2005 World Wide Web Consortium,
+
+   (Massachusetts Institute of Technology, European Research Consortium for
+   Informatics and Mathematics, Keio University). All Rights Reserved. This
+   work is distributed under the W3C® Software License [1] in the hope that
+   it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+   [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+   $Id: ws-addr.xsd,v 1.2 2008/07/23 13:38:16 plehegar Exp $
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.w3.org/2005/08/addressing" targetNamespace="http://www.w3.org/2005/08/addressing" blockDefault="#all" elementFormDefault="qualified" finalDefault="" attributeFormDefault="unqualified">
+	
+	<!-- Constructs from the WS-Addressing Core -->
+
+	<xs:element name="EndpointReference" type="tns:EndpointReferenceType"/>
+	<xs:complexType name="EndpointReferenceType" mixed="false">
+		<xs:sequence>
+			<xs:element name="Address" type="tns:AttributedURIType"/>
+			<xs:element ref="tns:ReferenceParameters" minOccurs="0"/>
+			<xs:element ref="tns:Metadata" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+	<xs:element name="ReferenceParameters" type="tns:ReferenceParametersType"/>
+	<xs:complexType name="ReferenceParametersType" mixed="false">
+		<xs:sequence>
+			<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+	<xs:element name="Metadata" type="tns:MetadataType"/>
+	<xs:complexType name="MetadataType" mixed="false">
+		<xs:sequence>
+			<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+	<xs:element name="MessageID" type="tns:AttributedURIType"/>
+	<xs:element name="RelatesTo" type="tns:RelatesToType"/>
+	<xs:complexType name="RelatesToType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:anyURI">
+				<xs:attribute name="RelationshipType" type="tns:RelationshipTypeOpenEnum" use="optional" default="http://www.w3.org/2005/08/addressing/reply"/>
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<xs:simpleType name="RelationshipTypeOpenEnum">
+		<xs:union memberTypes="tns:RelationshipType xs:anyURI"/>
+	</xs:simpleType>
+	
+	<xs:simpleType name="RelationshipType">
+		<xs:restriction base="xs:anyURI">
+			<xs:enumeration value="http://www.w3.org/2005/08/addressing/reply"/>
+		</xs:restriction>
+	</xs:simpleType>
+	
+	<xs:element name="ReplyTo" type="tns:EndpointReferenceType"/>
+	<xs:element name="From" type="tns:EndpointReferenceType"/>
+	<xs:element name="FaultTo" type="tns:EndpointReferenceType"/>
+	<xs:element name="To" type="tns:AttributedURIType"/>
+	<xs:element name="Action" type="tns:AttributedURIType"/>
+
+	<xs:complexType name="AttributedURIType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:anyURI">
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<!-- Constructs from the WS-Addressing SOAP binding -->
+
+	<xs:attribute name="IsReferenceParameter" type="xs:boolean"/>
+	
+	<xs:simpleType name="FaultCodesOpenEnumType">
+		<xs:union memberTypes="tns:FaultCodesType xs:QName"/>
+	</xs:simpleType>
+	
+	<xs:simpleType name="FaultCodesType">
+		<xs:restriction base="xs:QName">
+			<xs:enumeration value="tns:InvalidAddressingHeader"/>
+			<xs:enumeration value="tns:InvalidAddress"/>
+			<xs:enumeration value="tns:InvalidEPR"/>
+			<xs:enumeration value="tns:InvalidCardinality"/>
+			<xs:enumeration value="tns:MissingAddressInEPR"/>
+			<xs:enumeration value="tns:DuplicateMessageID"/>
+			<xs:enumeration value="tns:ActionMismatch"/>
+			<xs:enumeration value="tns:MessageAddressingHeaderRequired"/>
+			<xs:enumeration value="tns:DestinationUnreachable"/>
+			<xs:enumeration value="tns:ActionNotSupported"/>
+			<xs:enumeration value="tns:EndpointUnavailable"/>
+		</xs:restriction>
+	</xs:simpleType>
+	
+	<xs:element name="RetryAfter" type="tns:AttributedUnsignedLongType"/>
+	<xs:complexType name="AttributedUnsignedLongType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:unsignedLong">
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<xs:element name="ProblemHeaderQName" type="tns:AttributedQNameType"/>
+	<xs:complexType name="AttributedQNameType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:QName">
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<xs:element name="ProblemIRI" type="tns:AttributedURIType"/>
+	
+	<xs:element name="ProblemAction" type="tns:ProblemActionType"/>
+	<xs:complexType name="ProblemActionType" mixed="false">
+		<xs:sequence>
+			<xs:element ref="tns:Action" minOccurs="0"/>
+			<xs:element name="SoapAction" minOccurs="0" type="xs:anyURI"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+</xs:schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/jax-ws-catalog.xml	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<catalog prefer="system" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <system systemId="http://www.w3.org/2006/03/addressing/ws-addr.xsd" uri="./catalog/ws-addr.xsd"/>
+</catalog>
\ No newline at end of file
--- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -37,6 +37,7 @@
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
@@ -74,11 +75,30 @@
  * @run testng/othervm -DrunSecMngr=true transform.TransformerTest
  * @run testng/othervm transform.TransformerTest
  * @summary Transformer Tests
- * @bug 6272879 6305029 6505031 8150704 8162598 8169112 8169772
+ * @bug 6272879 6305029 6505031 8150704 8162598 8169112 8169631 8169772
  */
 @Listeners({jaxp.library.FilePolicy.class})
 public class TransformerTest {
 
+    // some global constants
+    private static final String LINE_SEPARATOR =
+        getSystemProperty("line.separator");
+
+    private static final String NAMESPACES =
+        "http://xml.org/sax/features/namespaces";
+
+    private static final String NAMESPACE_PREFIXES =
+        "http://xml.org/sax/features/namespace-prefixes";
+
+    private static abstract class TestTemplate {
+        protected void printSnippet(String title, String snippet) {
+            StringBuilder div = new StringBuilder();
+            for (int i = 0; i < title.length(); i++)
+                div.append("=");
+            System.out.println(title + "\n" + div + "\n" + snippet + "\n");
+        }
+    }
+
     /**
      * Reads the contents of the given file into a string.
      * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one.
@@ -101,44 +121,7 @@
         }
     }
 
-    /**
-     * Utility method for testBug8162598().
-     * Provides a convenient way to check/assert the expected namespaces
-     * of a Node and its siblings.
-     *
-     * @param test
-     * The node to check
-     * @param nstest
-     * Expected namespace of the node
-     * @param nsb
-     * Expected namespace of the first sibling
-     * @param nsc
-     * Expected namespace of the first sibling of the first sibling
-     */
-    private void checkNodeNS8162598(Node test, String nstest, String nsb, String nsc) {
-        String testNodeName = test.getNodeName();
-        if (nstest == null) {
-            Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName);
-        } else {
-            Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName);
-        }
-        Node b = test.getChildNodes().item(0);
-        if (nsb == null) {
-            Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b");
-        } else {
-            Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b");
-        }
-        Node c = b.getChildNodes().item(0);
-        if (nsc == null) {
-            Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c");
-        } else {
-            Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c");
-        }
-    }
-
     private class XMLReaderFor6305029 implements XMLReader {
-        private static final String NAMESPACES = "http://xml.org/sax/features/namespaces";
-        private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes";
         private boolean namespaces = true;
         private boolean namespacePrefixes = false;
         private EntityResolver resolver;
@@ -235,8 +218,6 @@
      */
     @Test
     public final void testBug6272879() throws IOException, TransformerException {
-        final String LINE_SEPARATOR = getSystemProperty("line.separator");
-
         final String xsl =
                 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
                 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR +
@@ -349,9 +330,125 @@
         Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value"));
     }
 
+    private static class Test8169631 extends TestTemplate {
+        private final static String xsl =
+            "<?xml version=\"1.0\"?>" + LINE_SEPARATOR +
+            "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR +
+            "  <xsl:template match=\"/\">" + LINE_SEPARATOR +
+            "    <xsl:variable name=\"Counter\" select=\"count(//row)\"/>" + LINE_SEPARATOR +
+            "    <xsl:variable name=\"AttribCounter\" select=\"count(//@attrib)\"/>" + LINE_SEPARATOR +
+            "    <Counter><xsl:value-of select=\"$Counter\"/></Counter>" + LINE_SEPARATOR +
+            "    <AttribCounter><xsl:value-of select=\"$AttribCounter\"/></AttribCounter>" + LINE_SEPARATOR +
+            "  </xsl:template>" + LINE_SEPARATOR +
+            "</xsl:stylesheet>" + LINE_SEPARATOR;
+
+        private final static String sourceXml =
+            "<?xml version=\"1.0\"?>" + LINE_SEPARATOR +
+            "<envelope xmlns=\"http://www.sap.com/myns\" xmlns:sap=\"http://www.sap.com/myns\">" + LINE_SEPARATOR +
+            "  <sap:row sap:attrib=\"a\">1</sap:row>" + LINE_SEPARATOR +
+            "  <row attrib=\"b\">2</row>" + LINE_SEPARATOR +
+            "  <row sap:attrib=\"c\">3</row>" + LINE_SEPARATOR +
+            "</envelope>" + LINE_SEPARATOR;
+
+        /**
+         * Utility method to print out transformation result and check values.
+         *
+         * @param type
+         * Text describing type of transformation
+         * @param result
+         * Resulting output of transformation
+         * @param elementCount
+         * Counter of elements to check
+         * @param attribCount
+         * Counter of attributes to check
+         */
+        private void verifyResult(String type, String result, int elementCount,
+                                  int attribCount)
+        {
+            printSnippet("Result of transformation from " + type + ":",
+                         result);
+            Assert.assertEquals(
+                result.contains("<Counter>" + elementCount + "</Counter>"),
+                true, "Result of transformation from " + type +
+                " should have count of " + elementCount + " elements.");
+            Assert.assertEquals(
+                result.contains("<AttribCounter>" + attribCount +
+                "</AttribCounter>"), true, "Result of transformation from " +
+                type + " should have count of "+ attribCount + " attributes.");
+        }
+
+        public void run() throws IOException, TransformerException,
+            SAXException, ParserConfigurationException
+        {
+            printSnippet("Source:", sourceXml);
+
+            printSnippet("Stylesheet:", xsl);
+
+            // create default transformer (namespace aware)
+            TransformerFactory tf1 = TransformerFactory.newInstance();
+            ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes());
+            Transformer t1 = tf1.newTransformer(new StreamSource(bais));
+
+            // test transformation from stream source with namespace support
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            bais = new ByteArrayInputStream(sourceXml.getBytes());
+            t1.transform(new StreamSource(bais), new StreamResult(baos));
+            verifyResult("StreamSource with namespace support", baos.toString(), 0, 1);
+
+            // test transformation from DOM source with namespace support
+            bais.reset();
+            baos.reset();
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            dbf.setNamespaceAware(true);
+            Document doc = dbf.newDocumentBuilder().parse(new InputSource(bais));
+            t1.transform(new DOMSource(doc), new StreamResult(baos));
+            verifyResult("DOMSource with namespace support", baos.toString(), 0, 1);
+
+            // test transformation from DOM source without namespace support
+            bais.reset();
+            baos.reset();
+            dbf.setNamespaceAware(false);
+            doc = dbf.newDocumentBuilder().parse(new InputSource(bais));
+            t1.transform(new DOMSource(doc), new StreamResult(baos));
+            verifyResult("DOMSource without namespace support", baos.toString(), 3, 3);
+
+            // test transformation from SAX source with namespace support
+            bais.reset();
+            baos.reset();
+            SAXParserFactory spf = SAXParserFactory.newInstance();
+            spf.setNamespaceAware(true);
+            XMLReader xmlr = spf.newSAXParser().getXMLReader();
+            SAXSource saxS = new SAXSource(xmlr, new InputSource(bais));
+            t1.transform(saxS, new StreamResult(baos));
+            verifyResult("SAXSource with namespace support", baos.toString(), 0, 1);
+
+            // test transformation from SAX source without namespace support
+            bais.reset();
+            baos.reset();
+            spf.setNamespaceAware(false);
+            xmlr = spf.newSAXParser().getXMLReader();
+            saxS = new SAXSource(xmlr, new InputSource(bais));
+            t1.transform(saxS, new StreamResult(baos));
+            verifyResult("SAXSource without namespace support", baos.toString(), 3, 3);
+        }
+    }
+
+    /*
+     * @bug 8169631
+     * @summary Test combinations of namespace awareness settings on
+     *          XSL transformations
+     */
+    @Test
+    public final void testBug8169631() throws IOException, SAXException,
+        TransformerException, ParserConfigurationException
+    {
+        new Test8169631().run();
+    }
+
     /*
      * @bug 8150704
-     * @summary Test that XSL transformation with lots of temporary result trees will not run out of DTM IDs.
+     * @summary Test that XSL transformation with lots of temporary result
+     *          trees will not run out of DTM IDs.
      */
     @Test
     public final void testBug8150704() throws TransformerException, IOException {
@@ -375,16 +472,8 @@
         System.out.println("Passed.");
     }
 
-    /*
-     * @bug 8162598
-     * @summary Test XSLTC handling of namespaces, especially empty namespace definitions to reset the
-     *          default namespace
-     */
-    @Test
-    public final void testBug8162598() throws IOException, TransformerException {
-        final String LINE_SEPARATOR = getSystemProperty("line.separator");
-
-        final String xsl =
+    private static class Test8162598 extends TestTemplate {
+        private static final String xsl =
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + LINE_SEPARATOR +
             "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR +
             "    <xsl:template match=\"/\">" + LINE_SEPARATOR +
@@ -402,39 +491,85 @@
             "    </xsl:template>" + LINE_SEPARATOR +
             "</xsl:stylesheet>";
 
-
-        final String sourceXml =
-                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aaa></aaa>" + LINE_SEPARATOR;
+        private static final String sourceXml =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aaa></aaa>" + LINE_SEPARATOR;
+        /**
+         * Utility method for testBug8162598().
+         * Provides a convenient way to check/assert the expected namespaces
+         * of a Node and its siblings.
+         *
+         * @param test
+         * The node to check
+         * @param nstest
+         * Expected namespace of the node
+         * @param nsb
+         * Expected namespace of the first sibling
+         * @param nsc
+         * Expected namespace of the first sibling of the first sibling
+         */
 
-        System.out.println("Stylesheet:");
-        System.out.println("=============================");
-        System.out.println(xsl);
-        System.out.println();
-
-        System.out.println("Source before transformation:");
-        System.out.println("=============================");
-        System.out.println(sourceXml);
-        System.out.println();
+        private void checkNodeNS(Node test, String nstest, String nsb, String nsc) {
+            String testNodeName = test.getNodeName();
+            if (nstest == null) {
+                Assert.assertNull(test.getNamespaceURI(), "unexpected namespace for " + testNodeName);
+            } else {
+                Assert.assertEquals(test.getNamespaceURI(), nstest, "unexpected namespace for " + testNodeName);
+            }
+            Node b = test.getChildNodes().item(0);
+            if (nsb == null) {
+                Assert.assertNull(b.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b");
+            } else {
+                Assert.assertEquals(b.getNamespaceURI(), nsb, "unexpected namespace for " + testNodeName + "->b");
+            }
+            Node c = b.getChildNodes().item(0);
+            if (nsc == null) {
+                Assert.assertNull(c.getNamespaceURI(), "unexpected namespace for " + testNodeName + "->b->c");
+            } else {
+                Assert.assertEquals(c.getNamespaceURI(), nsc, "unexpected namespace for " + testNodeName + "->b->c");
+            }
+        }
 
-        // transform to DOM result
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Transformer t = tf.newTransformer(new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
-        DOMResult result = new DOMResult();
-        t.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), result);
-        Document document = (Document)result.getNode();
+        public void run()  throws IOException, TransformerException {
+            printSnippet("Source:", sourceXml);
+
+            printSnippet("Stylesheet:", xsl);
+
+            // transform to DOM result
+            TransformerFactory tf = TransformerFactory.newInstance();
+            ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes());
+            Transformer t = tf.newTransformer(new StreamSource(bais));
+            DOMResult result = new DOMResult();
+            bais = new ByteArrayInputStream(sourceXml.getBytes());
+            t.transform(new StreamSource(bais), result);
+            Document document = (Document)result.getNode();
+
+            System.out.println("Result after transformation:");
+            System.out.println("============================");
+            OutputFormat format = new OutputFormat();
+            format.setIndenting(true);
+            new XMLSerializer(System.out, format).serialize(document);
+            System.out.println();
 
-        System.out.println("Result after transformation:");
-        System.out.println("============================");
-        OutputFormat format = new OutputFormat();
-        format.setIndenting(true);
-        new XMLSerializer(System.out, format).serialize(document);
-        System.out.println();
-        checkNodeNS8162598(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
-        checkNodeNS8162598(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null);
-        checkNodeNS8162598(document.getElementsByTagName("test3").item(0), null, null, null);
-        checkNodeNS8162598(document.getElementsByTagName("test4").item(0), null, null, null);
-        checkNodeNS8162598(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null);
-        Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(), "unexpected namespace for test6");
+            checkNodeNS(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
+            checkNodeNS(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null);
+            checkNodeNS(document.getElementsByTagName("test3").item(0), null, null, null);
+            checkNodeNS(document.getElementsByTagName("test4").item(0), null, null, null);
+            checkNodeNS(document.getElementsByTagName("test5").item(0), "ns1", "ns1", null);
+            Assert.assertNull(document.getElementsByTagName("test6").item(0).getNamespaceURI(),
+                "unexpected namespace for test6");
+        }
+    }
+
+    /*
+     * @bug 8162598
+     * @summary Test XSLTC handling of namespaces, especially empty namespace
+     *          definitions to reset the default namespace
+     */
+    @Test
+    public final void testBug8162598() throws IOException,
+        TransformerException
+    {
+        new Test8162598().run();
     }
 
     /**
--- a/jaxws/.hgtags	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/.hgtags	Wed Jul 05 22:42:01 2017 +0200
@@ -397,3 +397,4 @@
 72554d319b474b3636c7d02fe3c110254d111b1a jdk-9+149
 77e4e30d9d111272cd4a45a2203e8f570d40b12e jdk-9+150
 c48b4d4768b1c2b8fe5d1a844ca13732e5dfbe2a jdk-9+151
+6f8fb1cf7e5f61c40dcc3654f9a623c505f6de1f jdk-9+152
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,13 +47,13 @@
     public DetailEntry addDetailEntry(Name name) throws SOAPException {
         DetailEntry entry = createDetailEntry(name);
         addNode(entry);
-        return (DetailEntry) circumventBug5034339(entry);
+        return entry;
     }
 
     public DetailEntry addDetailEntry(QName qname) throws SOAPException {
         DetailEntry entry = createDetailEntry(qname);
         addNode(entry);
-        return (DetailEntry) circumventBug5034339(entry);
+        return entry;
     }
 
     protected SOAPElement addElement(Name name) throws SOAPException {
@@ -119,28 +119,4 @@
        return true;
    }
 
-    //overriding this method since the only two uses of this method
-    // are in ElementImpl and DetailImpl
-    //whereas the original base impl does the correct job for calls to it inside ElementImpl
-    // But it would not work for DetailImpl.
-    protected SOAPElement circumventBug5034339(SOAPElement element) {
-
-        Name elementName = element.getElementName();
-        if (!isNamespaceQualified(elementName)) {
-            String prefix = elementName.getPrefix();
-            String defaultNamespace = getNamespaceURI(prefix);
-            if (defaultNamespace != null) {
-                Name newElementName =
-                    NameImpl.create(
-                        elementName.getLocalName(),
-                        elementName.getPrefix(),
-                        defaultNamespace);
-                SOAPElement newElement = createDetailEntry(newElementName);
-                replaceChild(newElement, element);
-                return newElement;
-            }
-        }
-        return element;
-    }
-
 }
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -127,8 +127,11 @@
     }
 
     public SOAPElement addChildElement(String localName) throws SOAPException {
-        return (SOAPElement) addChildElement(
-            NameImpl.createFromUnqualifiedName(localName));
+        String nsUri = getNamespaceURI("");
+        Name name = (nsUri == null || nsUri.isEmpty())
+                ?  NameImpl.createFromUnqualifiedName(localName)
+                :  NameImpl.createFromQualifiedName(localName, nsUri);
+        return addChildElement(name);
     }
 
     public SOAPElement addChildElement(String localName, String prefix)
@@ -372,13 +375,13 @@
     protected SOAPElement addElement(Name name) throws SOAPException {
         SOAPElement newElement = createElement(name);
         addNode(newElement);
-        return circumventBug5034339(newElement);
+        return newElement;
     }
 
     protected SOAPElement addElement(QName name) throws SOAPException {
         SOAPElement newElement = createElement(name);
         addNode(newElement);
-        return circumventBug5034339(newElement);
+        return newElement;
     }
 
     protected SOAPElement createElement(Name name) {
@@ -1226,26 +1229,6 @@
         return !"".equals(name.getNamespaceURI());
     }
 
-    protected SOAPElement circumventBug5034339(SOAPElement element) {
-
-        Name elementName = element.getElementName();
-        if (!isNamespaceQualified(elementName)) {
-            String prefix = elementName.getPrefix();
-            String defaultNamespace = getNamespaceURI(prefix);
-            if (defaultNamespace != null) {
-                Name newElementName =
-                    NameImpl.create(
-                        elementName.getLocalName(),
-                        elementName.getPrefix(),
-                        defaultNamespace);
-                SOAPElement newElement = createElement(newElementName);
-                replaceChild(newElement, element);
-                return newElement;
-            }
-        }
-        return element;
-    }
-
     //TODO: This is a temporary SAAJ workaround for optimizing XWS
     // should be removed once the corresponding JAXP bug is fixed
     // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/util/stax/SaajStaxWriter.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,10 @@
 
 package com.sun.xml.internal.messaging.saaj.util.stax;
 
+import java.util.Iterator;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.List;
+import java.util.LinkedList;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
@@ -42,6 +44,17 @@
 /**
  * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface.
  *
+ * <p>
+ * Defers creation of SOAPElement until all the aspects of the name of the element are known.
+ * In some cases, the namespace uri is indicated only by the {@link #writeNamespace(String, String)} call.
+ * After opening an element ({@code writeStartElement}, {@code writeEmptyElement} methods), all attributes
+ * and namespace assignments are retained within {@link DeferredElement} object ({@code deferredElement} field).
+ * As soon as any other method than {@code writeAttribute}, {@code writeNamespace}, {@code writeDefaultNamespace}
+ * or {@code setNamespace} is called, the contents of {@code deferredElement} is transformed into new SOAPElement
+ * (which is appropriately inserted into the SOAPMessage under construction).
+ * This mechanism is necessary to fix JDK-8159058 issue.
+ * </p>
+ *
  * @author shih-chang.chen@oracle.com
  */
 public class SaajStaxWriter implements XMLStreamWriter {
@@ -49,6 +62,7 @@
     protected SOAPMessage soap;
     protected String envURI;
     protected SOAPElement currentElement;
+    protected DeferredElement deferredElement;
 
     static final protected String Envelope = "Envelope";
     static final protected String Header = "Header";
@@ -58,6 +72,7 @@
     public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException {
         soap = msg;
         this.envURI = uri;
+        this.deferredElement = new DeferredElement();
     }
 
     public SOAPMessage getSOAPMessage() {
@@ -70,11 +85,8 @@
 
     @Override
     public void writeStartElement(final String localName) throws XMLStreamException {
-        try {
-            currentElement = currentElement.addChildElement(localName);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
-        }
+        currentElement = deferredElement.flushTo(currentElement);
+        deferredElement.setLocalName(localName);
     }
 
     @Override
@@ -84,8 +96,10 @@
 
     @Override
     public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException {
-        try {
-            if (envURI.equals(ns)) {
+        currentElement = deferredElement.flushTo(currentElement);
+
+        if (envURI.equals(ns)) {
+            try {
                 if (Envelope.equals(ln)) {
                     currentElement = getEnvelope();
                     fixPrefix(prefix);
@@ -99,13 +113,16 @@
                     fixPrefix(prefix);
                     return;
                 }
+            } catch (SOAPException e) {
+                throw new XMLStreamException(e);
             }
-            currentElement = (prefix == null) ?
-                    currentElement.addChildElement(new QName(ns, ln)) :
-                    currentElement.addChildElement(ln, prefix, ns);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
+
         }
+
+        deferredElement.setLocalName(ln);
+        deferredElement.setNamespaceUri(ns);
+        deferredElement.setPrefix(prefix);
+
     }
 
     private void fixPrefix(final String prfx) throws XMLStreamException {
@@ -136,11 +153,13 @@
 
     @Override
     public void writeEndElement() throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         if (currentElement != null) currentElement = currentElement.getParentElement();
     }
 
     @Override
     public void writeEndDocument() throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
     }
 
     @Override
@@ -158,19 +177,14 @@
 
     @Override
     public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException {
-        try {
-            if (ns == null) {
-                if (prefix == null && xmlns.equals(ln)) {
-                    currentElement.addNamespaceDeclaration("", value);
-                } else {
-                    currentElement.setAttributeNS("", ln, value);
-                }
+        if (ns == null && prefix == null && xmlns.equals(ln)) {
+            writeNamespace("", value);
+        } else {
+            if (deferredElement.isInitialized()) {
+                deferredElement.addAttribute(prefix, ns, ln, value);
             } else {
-                QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix);
-                currentElement.addAttribute(name, value);
+                addAttibuteToElement(currentElement, prefix, ns, ln, value);
             }
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
         }
     }
 
@@ -181,16 +195,16 @@
 
     @Override
     public void writeNamespace(String prefix, final String uri) throws XMLStreamException {
-
         // make prefix default if null or "xmlns" (according to javadoc)
-        if (prefix == null || "xmlns".equals(prefix)) {
-            prefix = "";
-        }
-
-        try {
-            currentElement.addNamespaceDeclaration(prefix, uri);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
+        String thePrefix = prefix == null || "xmlns".equals(prefix) ? "" : prefix;
+        if (deferredElement.isInitialized()) {
+            deferredElement.addNamespaceDeclaration(thePrefix, uri);
+        } else {
+            try {
+                currentElement.addNamespaceDeclaration(thePrefix, uri);
+            } catch (SOAPException e) {
+                throw new XMLStreamException(e);
+            }
         }
     }
 
@@ -201,35 +215,40 @@
 
     @Override
     public void writeComment(final String data) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Comment c = soap.getSOAPPart().createComment(data);
         currentElement.appendChild(c);
     }
 
     @Override
     public void writeProcessingInstruction(final String target) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createProcessingInstruction(target, "");
         currentElement.appendChild(n);
     }
 
     @Override
     public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createProcessingInstruction(target, data);
         currentElement.appendChild(n);
     }
 
     @Override
     public void writeCData(final String data) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createCDATASection(data);
         currentElement.appendChild(n);
     }
 
     @Override
     public void writeDTD(final String dtd) throws XMLStreamException {
-        //TODO ... Don't do anything here
+        currentElement = deferredElement.flushTo(currentElement);
     }
 
     @Override
     public void writeEntityRef(final String name) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createEntityReference(name);
         currentElement.appendChild(n);
     }
@@ -257,6 +276,7 @@
 
     @Override
     public void writeCharacters(final String text) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         try {
             currentElement.addTextNode(text);
         } catch (SOAPException e) {
@@ -266,6 +286,7 @@
 
     @Override
     public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len);
         try {
             currentElement.addTextNode(new String(chr));
@@ -281,10 +302,16 @@
 
     @Override
     public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
-        try {
-            this.currentElement.addNamespaceDeclaration(prefix, uri);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
+        // TODO: this in fact is not what would be expected from XMLStreamWriter
+        //       (e.g. XMLStreamWriter for writing to output stream does not write anything as result of
+        //        this method, it just rememebers that given prefix is associated with the given uri
+        //        for the scope; to actually declare the prefix assignment in the resulting XML, one
+        //        needs to call writeNamespace(...) method
+        // Kept for backwards compatibility reasons - this might be worth of further investigation.
+        if (deferredElement.isInitialized()) {
+            deferredElement.addNamespaceDeclaration(prefix, uri);
+        } else {
+            throw new XMLStreamException("Namespace not associated with any element");
         }
     }
 
@@ -331,4 +358,209 @@
             }
         };
     }
+
+    static void addAttibuteToElement(SOAPElement element, String prefix, String ns, String ln, String value)
+            throws XMLStreamException {
+        try {
+            if (ns == null) {
+                element.setAttributeNS("", ln, value);
+            } else {
+                QName name = prefix == null ? new QName(ns, ln) : new QName(ns, ln, prefix);
+                element.addAttribute(name, value);
+            }
+        } catch (SOAPException e) {
+            throw new XMLStreamException(e);
+        }
+    }
+
+    /**
+     * Holds details of element that needs to be deferred in order to manage namespace assignments correctly.
+     *
+     * <p>
+     * An instance of can be set with all the aspects of the element name (local name, prefix, namespace uri).
+     * Attributes and namespace declarations (special case of attribute) can be added.
+     * Namespace declarations are handled so that the element namespace is updated if it is implied by the namespace
+     * declaration and the namespace was not set to non-{@code null} value previously.
+     * </p>
+     *
+     * <p>
+     * The state of this object can be {@link #flushTo(SOAPElement) flushed} to SOAPElement - new SOAPElement will
+     * be added a child element; the new element will have exactly the shape as represented by the state of this
+     * object. Note that the {@link #flushTo(SOAPElement)} method does nothing
+     * (and returns the argument immediately) if the state of this object is not initialized
+     * (i.e. local name is null).
+     * </p>
+     *
+     * @author ondrej.cerny@oracle.com
+     */
+    static class DeferredElement {
+        private String prefix;
+        private String localName;
+        private String namespaceUri;
+        private final List<NamespaceDeclaration> namespaceDeclarations;
+        private final List<AttributeDeclaration> attributeDeclarations;
+
+        DeferredElement() {
+            this.namespaceDeclarations = new LinkedList<NamespaceDeclaration>();
+            this.attributeDeclarations = new LinkedList<AttributeDeclaration>();
+            reset();
+        }
+
+
+        /**
+         * Set prefix of the element.
+         * @param prefix namespace prefix
+         */
+        public void setPrefix(final String prefix) {
+            this.prefix = prefix;
+        }
+
+        /**
+         * Set local name of the element.
+         *
+         * <p>
+         *     This method initializes the element.
+         * </p>
+         *
+         * @param localName local name {@code not null}
+         */
+        public void setLocalName(final String localName) {
+            if (localName == null) {
+                throw new IllegalArgumentException("localName can not be null");
+            }
+            this.localName = localName;
+        }
+
+        /**
+         * Set namespace uri.
+         *
+         * @param namespaceUri namespace uri
+         */
+        public void setNamespaceUri(final String namespaceUri) {
+            this.namespaceUri = namespaceUri;
+        }
+
+        /**
+         * Adds namespace prefix assignment to the element.
+         *
+         * @param prefix prefix (not {@code null})
+         * @param namespaceUri namespace uri
+         */
+        public void addNamespaceDeclaration(final String prefix, final String namespaceUri) {
+            if (null == this.namespaceUri && null != namespaceUri && prefix.equals(emptyIfNull(this.prefix))) {
+                this.namespaceUri = namespaceUri;
+            }
+            this.namespaceDeclarations.add(new NamespaceDeclaration(prefix, namespaceUri));
+        }
+
+        /**
+         * Adds attribute to the element.
+         * @param prefix prefix
+         * @param ns namespace
+         * @param ln local name
+         * @param value value
+         */
+        public void addAttribute(final String prefix, final String ns, final String ln, final String value) {
+            if (ns == null && prefix == null && xmlns.equals(ln)) {
+                this.addNamespaceDeclaration(prefix, value);
+            } else {
+                this.attributeDeclarations.add(new AttributeDeclaration(prefix, ns, ln, value));
+            }
+        }
+
+        /**
+         * Flushes state of this element to the {@code target} element.
+         *
+         * <p>
+         * If this element is initialized then it is added with all the namespace declarations and attributes
+         * to the {@code target} element as a child. The state of this element is reset to uninitialized.
+         * The newly added element object is returned.
+         * </p>
+         * <p>
+         * If this element is not initialized then the {@code target} is returned immediately, nothing else is done.
+         * </p>
+         *
+         * @param target target element
+         * @return {@code target} or new element
+         * @throws XMLStreamException on error
+         */
+        public SOAPElement flushTo(final SOAPElement target) throws XMLStreamException {
+            try {
+                if (this.localName != null) {
+                    // add the element appropriately (based on namespace declaration)
+                    final SOAPElement newElement;
+                    if (this.namespaceUri == null) {
+                        // add element with inherited scope
+                        newElement = target.addChildElement(this.localName);
+                    } else if (prefix == null) {
+                        newElement = target.addChildElement(new QName(this.namespaceUri, this.localName));
+                    } else {
+                        newElement = target.addChildElement(this.localName, this.prefix, this.namespaceUri);
+                    }
+                    // add namespace declarations
+                    for (NamespaceDeclaration namespace : this.namespaceDeclarations) {
+                        target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri);
+                    }
+                    // add attribute declarations
+                    for (AttributeDeclaration attribute : this.attributeDeclarations) {
+                        addAttibuteToElement(newElement,
+                                attribute.prefix, attribute.namespaceUri, attribute.localName, attribute.value);
+                    }
+                    // reset state
+                    this.reset();
+
+                    return newElement;
+                } else {
+                    return target;
+                }
+                // else after reset state -> not initialized
+            } catch (SOAPException e) {
+                throw new XMLStreamException(e);
+            }
+        }
+
+        /**
+         * Is the element initialized?
+         * @return boolean indicating whether it was initialized after last flush
+         */
+        public boolean isInitialized() {
+            return this.localName != null;
+        }
+
+        private void reset() {
+            this.localName = null;
+            this.prefix = null;
+            this.namespaceUri = null;
+            this.namespaceDeclarations.clear();
+            this.attributeDeclarations.clear();
+        }
+
+        private static String emptyIfNull(String s) {
+            return s == null ? "" : s;
+        }
+    }
+
+    static class NamespaceDeclaration {
+        final String prefix;
+        final String namespaceUri;
+
+        NamespaceDeclaration(String prefix, String namespaceUri) {
+            this.prefix = prefix;
+            this.namespaceUri = namespaceUri;
+        }
+    }
+
+    static class AttributeDeclaration {
+        final String prefix;
+        final String namespaceUri;
+        final String localName;
+        final String value;
+
+        AttributeDeclaration(String prefix, String namespaceUri, String localName, String value) {
+            this.prefix = prefix;
+            this.namespaceUri = namespaceUri;
+            this.localName = localName;
+            this.value = value;
+        }
+    }
 }
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,10 @@
 
 package com.sun.xml.internal.ws.api.message.saaj;
 
+import java.util.Iterator;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.List;
+import java.util.LinkedList;
 
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
@@ -42,6 +44,17 @@
 /**
  * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface.
  *
+ * <p>
+ * Defers creation of SOAPElement until all the aspects of the name of the element are known.
+ * In some cases, the namespace uri is indicated only by the {@link #writeNamespace(String, String)} call.
+ * After opening an element ({@code writeStartElement}, {@code writeEmptyElement} methods), all attributes
+ * and namespace assignments are retained within {@link DeferredElement} object ({@code deferredElement} field).
+ * As soon as any other method than {@code writeAttribute}, {@code writeNamespace}, {@code writeDefaultNamespace}
+ * or {@code setNamespace} is called, the contents of {@code deferredElement} is transformed into new SOAPElement
+ * (which is appropriately inserted into the SOAPMessage under construction).
+ * This mechanism is necessary to fix JDK-8159058 issue.
+ * </p>
+ *
  * @author shih-chang.chen@oracle.com
  */
 public class SaajStaxWriter implements XMLStreamWriter {
@@ -49,6 +62,7 @@
     protected SOAPMessage soap;
     protected String envURI;
     protected SOAPElement currentElement;
+    protected DeferredElement deferredElement;
 
     static final protected String Envelope = "Envelope";
     static final protected String Header = "Header";
@@ -58,6 +72,7 @@
     public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException {
         soap = msg;
         this.envURI = uri;
+        this.deferredElement = new DeferredElement();
     }
 
     public SOAPMessage getSOAPMessage() {
@@ -70,11 +85,8 @@
 
     @Override
     public void writeStartElement(final String localName) throws XMLStreamException {
-        try {
-            currentElement = currentElement.addChildElement(localName);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
-        }
+        currentElement = deferredElement.flushTo(currentElement);
+        deferredElement.setLocalName(localName);
     }
 
     @Override
@@ -84,8 +96,10 @@
 
     @Override
     public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException {
-        try {
-            if (envURI.equals(ns)) {
+        currentElement = deferredElement.flushTo(currentElement);
+
+        if (envURI.equals(ns)) {
+            try {
                 if (Envelope.equals(ln)) {
                     currentElement = getEnvelope();
                     fixPrefix(prefix);
@@ -99,13 +113,16 @@
                     fixPrefix(prefix);
                     return;
                 }
+            } catch (SOAPException e) {
+                throw new XMLStreamException(e);
             }
-            currentElement = (prefix == null) ?
-                    currentElement.addChildElement(new QName(ns, ln)) :
-                    currentElement.addChildElement(ln, prefix, ns);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
+
         }
+
+        deferredElement.setLocalName(ln);
+        deferredElement.setNamespaceUri(ns);
+        deferredElement.setPrefix(prefix);
+
     }
 
     private void fixPrefix(final String prfx) throws XMLStreamException {
@@ -136,11 +153,13 @@
 
     @Override
     public void writeEndElement() throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         if (currentElement != null) currentElement = currentElement.getParentElement();
     }
 
     @Override
     public void writeEndDocument() throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
     }
 
     @Override
@@ -158,19 +177,14 @@
 
     @Override
     public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException {
-        try {
-            if (ns == null) {
-                if (prefix == null && xmlns.equals(ln)) {
-                    currentElement.addNamespaceDeclaration("", value);
-                } else {
-                    currentElement.setAttributeNS("", ln, value);
-                }
+        if (ns == null && prefix == null && xmlns.equals(ln)) {
+            writeNamespace("", value);
+        } else {
+            if (deferredElement.isInitialized()) {
+                deferredElement.addAttribute(prefix, ns, ln, value);
             } else {
-                QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix);
-                currentElement.addAttribute(name, value);
+                addAttibuteToElement(currentElement, prefix, ns, ln, value);
             }
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
         }
     }
 
@@ -181,16 +195,16 @@
 
     @Override
     public void writeNamespace(String prefix, final String uri) throws XMLStreamException {
-
         // make prefix default if null or "xmlns" (according to javadoc)
-        if (prefix == null || "xmlns".equals(prefix)) {
-            prefix = "";
-        }
-
-        try {
-            currentElement.addNamespaceDeclaration(prefix, uri);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
+        String thePrefix = prefix == null || "xmlns".equals(prefix) ? "" : prefix;
+        if (deferredElement.isInitialized()) {
+            deferredElement.addNamespaceDeclaration(thePrefix, uri);
+        } else {
+            try {
+                currentElement.addNamespaceDeclaration(thePrefix, uri);
+            } catch (SOAPException e) {
+                throw new XMLStreamException(e);
+            }
         }
     }
 
@@ -201,35 +215,40 @@
 
     @Override
     public void writeComment(final String data) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Comment c = soap.getSOAPPart().createComment(data);
         currentElement.appendChild(c);
     }
 
     @Override
     public void writeProcessingInstruction(final String target) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createProcessingInstruction(target, "");
         currentElement.appendChild(n);
     }
 
     @Override
     public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createProcessingInstruction(target, data);
         currentElement.appendChild(n);
     }
 
     @Override
     public void writeCData(final String data) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createCDATASection(data);
         currentElement.appendChild(n);
     }
 
     @Override
     public void writeDTD(final String dtd) throws XMLStreamException {
-        //TODO ... Don't do anything here
+        currentElement = deferredElement.flushTo(currentElement);
     }
 
     @Override
     public void writeEntityRef(final String name) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         Node n = soap.getSOAPPart().createEntityReference(name);
         currentElement.appendChild(n);
     }
@@ -257,6 +276,7 @@
 
     @Override
     public void writeCharacters(final String text) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         try {
             currentElement.addTextNode(text);
         } catch (SOAPException e) {
@@ -266,6 +286,7 @@
 
     @Override
     public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+        currentElement = deferredElement.flushTo(currentElement);
         char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len);
         try {
             currentElement.addTextNode(new String(chr));
@@ -281,10 +302,16 @@
 
     @Override
     public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
-        try {
-            this.currentElement.addNamespaceDeclaration(prefix, uri);
-        } catch (SOAPException e) {
-            throw new XMLStreamException(e);
+        // TODO: this in fact is not what would be expected from XMLStreamWriter
+        //       (e.g. XMLStreamWriter for writing to output stream does not write anything as result of
+        //        this method, it just rememebers that given prefix is associated with the given uri
+        //        for the scope; to actually declare the prefix assignment in the resulting XML, one
+        //        needs to call writeNamespace(...) method
+        // Kept for backwards compatibility reasons - this might be worth of further investigation.
+        if (deferredElement.isInitialized()) {
+            deferredElement.addNamespaceDeclaration(prefix, uri);
+        } else {
+            throw new XMLStreamException("Namespace not associated with any element");
         }
     }
 
@@ -315,12 +342,12 @@
                 return currentElement.lookupPrefix(namespaceURI);
             }
             public Iterator getPrefixes(final String namespaceURI) {
-                return new Iterator() {
+                return new Iterator<String>() {
                     String prefix = getPrefix(namespaceURI);
                     public boolean hasNext() {
                         return (prefix != null);
                     }
-                    public Object next() {
+                    public String next() {
                         if (!hasNext()) throw new java.util.NoSuchElementException();
                         String next = prefix;
                         prefix = null;
@@ -331,4 +358,209 @@
             }
         };
     }
+
+    static void addAttibuteToElement(SOAPElement element, String prefix, String ns, String ln, String value)
+            throws XMLStreamException {
+        try {
+            if (ns == null) {
+                element.setAttributeNS("", ln, value);
+            } else {
+                QName name = prefix == null ? new QName(ns, ln) : new QName(ns, ln, prefix);
+                element.addAttribute(name, value);
+            }
+        } catch (SOAPException e) {
+            throw new XMLStreamException(e);
+        }
+    }
+
+    /**
+     * Holds details of element that needs to be deferred in order to manage namespace assignments correctly.
+     *
+     * <p>
+     * An instance of can be set with all the aspects of the element name (local name, prefix, namespace uri).
+     * Attributes and namespace declarations (special case of attribute) can be added.
+     * Namespace declarations are handled so that the element namespace is updated if it is implied by the namespace
+     * declaration and the namespace was not set to non-{@code null} value previously.
+     * </p>
+     *
+     * <p>
+     * The state of this object can be {@link #flushTo(SOAPElement) flushed} to SOAPElement - new SOAPElement will
+     * be added a child element; the new element will have exactly the shape as represented by the state of this
+     * object. Note that the {@link #flushTo(SOAPElement)} method does nothing
+     * (and returns the argument immediately) if the state of this object is not initialized
+     * (i.e. local name is null).
+     * </p>
+     *
+     * @author ondrej.cerny@oracle.com
+     */
+    static class DeferredElement {
+        private String prefix;
+        private String localName;
+        private String namespaceUri;
+        private final List<NamespaceDeclaration> namespaceDeclarations;
+        private final List<AttributeDeclaration> attributeDeclarations;
+
+        DeferredElement() {
+            this.namespaceDeclarations = new LinkedList<NamespaceDeclaration>();
+            this.attributeDeclarations = new LinkedList<AttributeDeclaration>();
+            reset();
+        }
+
+
+        /**
+         * Set prefix of the element.
+         * @param prefix namespace prefix
+         */
+        public void setPrefix(final String prefix) {
+            this.prefix = prefix;
+        }
+
+        /**
+         * Set local name of the element.
+         *
+         * <p>
+         *     This method initializes the element.
+         * </p>
+         *
+         * @param localName local name {@code not null}
+         */
+        public void setLocalName(final String localName) {
+            if (localName == null) {
+                throw new IllegalArgumentException("localName can not be null");
+            }
+            this.localName = localName;
+        }
+
+        /**
+         * Set namespace uri.
+         *
+         * @param namespaceUri namespace uri
+         */
+        public void setNamespaceUri(final String namespaceUri) {
+            this.namespaceUri = namespaceUri;
+        }
+
+        /**
+         * Adds namespace prefix assignment to the element.
+         *
+         * @param prefix prefix (not {@code null})
+         * @param namespaceUri namespace uri
+         */
+        public void addNamespaceDeclaration(final String prefix, final String namespaceUri) {
+            if (null == this.namespaceUri && null != namespaceUri && prefix.equals(emptyIfNull(this.prefix))) {
+                this.namespaceUri = namespaceUri;
+            }
+            this.namespaceDeclarations.add(new NamespaceDeclaration(prefix, namespaceUri));
+        }
+
+        /**
+         * Adds attribute to the element.
+         * @param prefix prefix
+         * @param ns namespace
+         * @param ln local name
+         * @param value value
+         */
+        public void addAttribute(final String prefix, final String ns, final String ln, final String value) {
+            if (ns == null && prefix == null && xmlns.equals(ln)) {
+                this.addNamespaceDeclaration(prefix, value);
+            } else {
+                this.attributeDeclarations.add(new AttributeDeclaration(prefix, ns, ln, value));
+            }
+        }
+
+        /**
+         * Flushes state of this element to the {@code target} element.
+         *
+         * <p>
+         * If this element is initialized then it is added with all the namespace declarations and attributes
+         * to the {@code target} element as a child. The state of this element is reset to uninitialized.
+         * The newly added element object is returned.
+         * </p>
+         * <p>
+         * If this element is not initialized then the {@code target} is returned immediately, nothing else is done.
+         * </p>
+         *
+         * @param target target element
+         * @return {@code target} or new element
+         * @throws XMLStreamException on error
+         */
+        public SOAPElement flushTo(final SOAPElement target) throws XMLStreamException {
+            try {
+                if (this.localName != null) {
+                    // add the element appropriately (based on namespace declaration)
+                    final SOAPElement newElement;
+                    if (this.namespaceUri == null) {
+                        // add element with inherited scope
+                        newElement = target.addChildElement(this.localName);
+                    } else if (prefix == null) {
+                        newElement = target.addChildElement(new QName(this.namespaceUri, this.localName));
+                    } else {
+                        newElement = target.addChildElement(this.localName, this.prefix, this.namespaceUri);
+                    }
+                    // add namespace declarations
+                    for (NamespaceDeclaration namespace : this.namespaceDeclarations) {
+                        target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri);
+                    }
+                    // add attribute declarations
+                    for (AttributeDeclaration attribute : this.attributeDeclarations) {
+                        addAttibuteToElement(newElement,
+                                attribute.prefix, attribute.namespaceUri, attribute.localName, attribute.value);
+                    }
+                    // reset state
+                    this.reset();
+
+                    return newElement;
+                } else {
+                    return target;
+                }
+                // else after reset state -> not initialized
+            } catch (SOAPException e) {
+                throw new XMLStreamException(e);
+            }
+        }
+
+        /**
+         * Is the element initialized?
+         * @return boolean indicating whether it was initialized after last flush
+         */
+        public boolean isInitialized() {
+            return this.localName != null;
+        }
+
+        private void reset() {
+            this.localName = null;
+            this.prefix = null;
+            this.namespaceUri = null;
+            this.namespaceDeclarations.clear();
+            this.attributeDeclarations.clear();
+        }
+
+        private static String emptyIfNull(String s) {
+            return s == null ? "" : s;
+        }
+    }
+
+    static class NamespaceDeclaration {
+        final String prefix;
+        final String namespaceUri;
+
+        NamespaceDeclaration(String prefix, String namespaceUri) {
+            this.prefix = prefix;
+            this.namespaceUri = namespaceUri;
+        }
+    }
+
+    static class AttributeDeclaration {
+        final String prefix;
+        final String namespaceUri;
+        final String localName;
+        final String value;
+
+        AttributeDeclaration(String prefix, String namespaceUri, String localName, String value) {
+            this.prefix = prefix;
+            this.namespaceUri = namespaceUri;
+            this.localName = localName;
+            this.value = value;
+        }
+    }
 }
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/xml/XmlUtil.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.lang.reflect.Method;
+import java.net.URI;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -332,13 +333,13 @@
      * (com.sun.org.apache.xml.internal) for modular runtime.
      */
     private static EntityResolver createCatalogResolver(ArrayList<URL> urls) throws Exception {
-        // Prepare array of catalog paths
-        String[] paths = urls.stream()
-                             .map(u -> u.toExternalForm())
-                             .toArray(c -> new String[c]);
+        // Prepare array of catalog URIs
+        URI[] uris = urls.stream()
+                             .map(u -> URI.create(u.toExternalForm()))
+                             .toArray(URI[]::new);
 
         //Create CatalogResolver with new JDK9+ API
-        return (EntityResolver) CatalogManager.catalogResolver(catalogFeatures, paths);
+        return (EntityResolver) CatalogManager.catalogResolver(catalogFeatures, uris);
     }
 
     // Cache CatalogFeatures instance for future usages.
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/Options.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -777,13 +777,13 @@
      * Adds a new catalog file.
      */
     public void addCatalog(File catalogFile) throws IOException {
-        String newUrl = catalogFile.getPath();
+        URI newUrl = catalogFile.toURI();
         if (!catalogUrls.contains(newUrl)) {
             catalogUrls.add(newUrl);
         }
         try {
             entityResolver = CatalogManager.catalogResolver(catalogFeatures,
-                                catalogUrls.toArray(new String[0]));
+                                catalogUrls.stream().toArray(URI[]::new));
         } catch (Exception ex) {
             entityResolver = null;
         }
@@ -791,7 +791,7 @@
 
     // Since javax.xml.catalog is unmodifiable we need to track catalog
     // URLs added and create new catalog each time addCatalog is called
-    private final ArrayList<String> catalogUrls = new ArrayList<String>();
+    private final ArrayList<URI> catalogUrls = new ArrayList<>();
 
     // Cache CatalogFeatures instance for future usages.
     // Resolve feature is set to "continue" value for backward compatibility.
--- a/jdk/.hgtags	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/.hgtags	Wed Jul 05 22:42:01 2017 +0200
@@ -394,3 +394,4 @@
 5a846396a24c7aff01d6a8feaa7afc0a6369f04d jdk-9+149
 71e198ef3839045e829a879af1d709be16ab0f88 jdk-9+150
 d27bab22ff62823902d93d1d35ca397cfd50d059 jdk-9+151
+a20f2cf90762673e1bc4980fd6597e70a2578045 jdk-9+152
--- a/jdk/make/data/fontconfig/solaris.fontconfig.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/make/data/fontconfig/solaris.fontconfig.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -436,15 +436,15 @@
 
 filename.-monotype-arial-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arial.ttf
 filename.-monotype-arial-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/ariali.ttf
-filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialb.ttf
+filename.-monotype-arial-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbd.ttf
 filename.-monotype-arial-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/arialbi.ttf
 filename.-monotype-courier_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/cour.ttf
 filename.-monotype-courier_new-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/couri.ttf
-filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courb.ttf
+filename.-monotype-courier_new-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbd.ttf
 filename.-monotype-courier_new-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/courbi.ttf
 filename.-monotype-times_new_roman-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/times.ttf
 filename.-monotype-times_new_roman-medium-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesi.ttf
-filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesb.ttf
+filename.-monotype-times_new_roman-bold-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbd.ttf
 filename.-monotype-times_new_roman-bold-i-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/timesbi.ttf
 
 filename.-monotype-angsana_new-medium-r-normal--*-%d-*-*-p-*-iso10646-1=/usr/share/fonts/TrueType/core/angsa.ttf
--- a/jdk/make/lib/Awt2dLibraries.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -222,6 +222,8 @@
 # applies to debug builds.
 ifeq ($(TOOLCHAIN_TYPE), gcc)
   BUILD_LIBAWT_debug_mem.c_CFLAGS := -w
+  # This option improves performance of MaskFill in Java2D by 20% for some gcc
+  LIBAWT_CFLAGS += -fgcse-after-reload
 endif
 
 $(eval $(call SetupNativeCompilation,BUILD_LIBAWT, \
--- a/jdk/src/java.base/share/classes/java/io/File.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/io/File.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1962,6 +1962,9 @@
                 name = sb.toString();
             }
 
+            // Normalize the path component
+            name = fs.normalize(name);
+
             File f = new File(dir, name);
             if (!name.equals(f.getName()) || f.isInvalid()) {
                 if (System.getSecurityManager() != null)
--- a/jdk/src/java.base/share/classes/java/lang/Class.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2477,7 +2477,7 @@
      * <ul>
      *
      * <li> If the {@code name} begins with a {@code '/'}
-     * (<tt>'&#92;u002f'</tt>), then the absolute name of the resource is the
+     * (<code>'&#92;u002f'</code>), then the absolute name of the resource is the
      * portion of the {@code name} following the {@code '/'}.
      *
      * <li> Otherwise, the absolute name is of the following form:
@@ -2488,7 +2488,7 @@
      *
      * <p> Where the {@code modified_package_name} is the package name of this
      * object with {@code '/'} substituted for {@code '.'}
-     * (<tt>'&#92;u002e'</tt>).
+     * (<code>'&#92;u002e'</code>).
      *
      * </ul>
      *
@@ -2570,7 +2570,7 @@
      * <ul>
      *
      * <li> If the {@code name} begins with a {@code '/'}
-     * (<tt>'&#92;u002f'</tt>), then the absolute name of the resource is the
+     * (<code>'&#92;u002f'</code>), then the absolute name of the resource is the
      * portion of the {@code name} following the {@code '/'}.
      *
      * <li> Otherwise, the absolute name is of the following form:
@@ -2581,7 +2581,7 @@
      *
      * <p> Where the {@code modified_package_name} is the package name of this
      * object with {@code '/'} substituted for {@code '.'}
-     * (<tt>'&#92;u002e'</tt>).
+     * (<code>'&#92;u002e'</code>).
      *
      * </ul>
      *
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,34 +70,34 @@
 
 /**
  * A class loader is an object that is responsible for loading classes. The
- * class <tt>ClassLoader</tt> is an abstract class.  Given the <a
+ * class {@code ClassLoader} is an abstract class.  Given the <a
  * href="#name">binary name</a> of a class, a class loader should attempt to
  * locate or generate data that constitutes a definition for the class.  A
  * typical strategy is to transform the name into a file name and then read a
  * "class file" of that name from a file system.
  *
- * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
- * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
+ * <p> Every {@link java.lang.Class Class} object contains a {@link
+ * Class#getClassLoader() reference} to the {@code ClassLoader} that defined
  * it.
  *
- * <p> <tt>Class</tt> objects for array classes are not created by class
+ * <p> {@code Class} objects for array classes are not created by class
  * loaders, but are created automatically as required by the Java runtime.
  * The class loader for an array class, as returned by {@link
  * Class#getClassLoader()} is the same as the class loader for its element
  * type; if the element type is a primitive type, then the array class has no
  * class loader.
  *
- * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
+ * <p> Applications implement subclasses of {@code ClassLoader} in order to
  * extend the manner in which the Java virtual machine dynamically loads
  * classes.
  *
  * <p> Class loaders may typically be used by security managers to indicate
  * security domains.
  *
- * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
- * classes and resources.  Each instance of <tt>ClassLoader</tt> has an
+ * <p> The {@code ClassLoader} class uses a delegation model to search for
+ * classes and resources.  Each instance of {@code ClassLoader} has an
  * associated parent class loader.  When requested to find a class or
- * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
+ * resource, a {@code ClassLoader} instance will delegate the search for the
  * class or resource to its parent class loader before attempting to find the
  * class or resource itself.
  *
@@ -105,15 +105,15 @@
  * <em>{@linkplain #isRegisteredAsParallelCapable() parallel capable}</em> class
  * loaders and are required to register themselves at their class initialization
  * time by invoking the {@link
- * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
- * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
+ * #registerAsParallelCapable ClassLoader.registerAsParallelCapable}
+ * method. Note that the {@code ClassLoader} class is registered as parallel
  * capable by default. However, its subclasses still need to register themselves
  * if they are parallel capable.
  * In environments in which the delegation model is not strictly
  * hierarchical, class loaders need to be parallel capable, otherwise class
  * loading can lead to deadlocks because the loader lock is held for the
  * duration of the class loading process (see {@link #loadClass
- * <tt>loadClass</tt>} methods).
+ * loadClass} methods).
  *
  * <h3> <a name="builtinLoaders">Run-time Built-in Class Loaders</a></h3>
  *
@@ -143,13 +143,13 @@
  * However, some classes may not originate from a file; they may originate
  * from other sources, such as the network, or they could be constructed by an
  * application.  The method {@link #defineClass(String, byte[], int, int)
- * <tt>defineClass</tt>} converts an array of bytes into an instance of class
- * <tt>Class</tt>. Instances of this newly defined class can be created using
- * {@link Class#newInstance <tt>Class.newInstance</tt>}.
+ * defineClass} converts an array of bytes into an instance of class
+ * {@code Class}. Instances of this newly defined class can be created using
+ * {@link Class#newInstance Class.newInstance}.
  *
  * <p> The methods and constructors of objects created by a class loader may
  * reference other classes.  To determine the class(es) referred to, the Java
- * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of
+ * virtual machine invokes the {@link #loadClass loadClass} method of
  * the class loader that originally created the class.
  *
  * <p> For example, an application could create a network class loader to
@@ -162,9 +162,9 @@
  * </pre></blockquote>
  *
  * <p> The network class loader subclass must define the methods {@link
- * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
+ * #findClass findClass} and {@code loadClassData} to load a class
  * from the network.  Once it has downloaded the bytes that make up the class,
- * it should use the method {@link #defineClass <tt>defineClass</tt>} to
+ * it should use the method {@link #defineClass defineClass} to
  * create a class instance.  A sample implementation is:
  *
  * <blockquote><pre>
@@ -392,7 +392,7 @@
      *
      * <p> If there is a security manager, its {@link
      * SecurityManager#checkCreateClassLoader()
-     * <tt>checkCreateClassLoader</tt>} method is invoked.  This may result in
+     * checkCreateClassLoader} method is invoked.  This may result in
      * a security exception.  </p>
      *
      * @param  parent
@@ -400,7 +400,7 @@
      *
      * @throws  SecurityException
      *          If a security manager exists and its
-     *          <tt>checkCreateClassLoader</tt> method doesn't allow creation
+     *          {@code checkCreateClassLoader} method doesn't allow creation
      *          of a new class loader.
      *
      * @since  1.2
@@ -410,18 +410,18 @@
     }
 
     /**
-     * Creates a new class loader using the <tt>ClassLoader</tt> returned by
+     * Creates a new class loader using the {@code ClassLoader} returned by
      * the method {@link #getSystemClassLoader()
-     * <tt>getSystemClassLoader()</tt>} as the parent class loader.
+     * getSystemClassLoader()} as the parent class loader.
      *
      * <p> If there is a security manager, its {@link
      * SecurityManager#checkCreateClassLoader()
-     * <tt>checkCreateClassLoader</tt>} method is invoked.  This may result in
+     * checkCreateClassLoader} method is invoked.  This may result in
      * a security exception.  </p>
      *
      * @throws  SecurityException
      *          If a security manager exists and its
-     *          <tt>checkCreateClassLoader</tt> method doesn't allow creation
+     *          {@code checkCreateClassLoader} method doesn't allow creation
      *          of a new class loader.
      */
     protected ClassLoader() {
@@ -458,13 +458,13 @@
      * This method searches for classes in the same manner as the {@link
      * #loadClass(String, boolean)} method.  It is invoked by the Java virtual
      * machine to resolve class references.  Invoking this method is equivalent
-     * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
-     * false)</tt>}.
+     * to invoking {@link #loadClass(String, boolean) loadClass(name,
+     * false)}.
      *
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
-     * @return  The resulting <tt>Class</tt> object
+     * @return  The resulting {@code Class} object
      *
      * @throws  ClassNotFoundException
      *          If the class was not found
@@ -483,8 +483,8 @@
      *   <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
      *   has already been loaded.  </p></li>
      *
-     *   <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
-     *   on the parent class loader.  If the parent is <tt>null</tt> the class
+     *   <li><p> Invoke the {@link #loadClass(String) loadClass} method
+     *   on the parent class loader.  If the parent is {@code null} the class
      *   loader built-in to the virtual machine is used, instead.  </p></li>
      *
      *   <li><p> Invoke the {@link #findClass(String)} method to find the
@@ -493,23 +493,23 @@
      * </ol>
      *
      * <p> If the class was found using the above steps, and the
-     * <tt>resolve</tt> flag is true, this method will then invoke the {@link
-     * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
+     * {@code resolve} flag is true, this method will then invoke the {@link
+     * #resolveClass(Class)} method on the resulting {@code Class} object.
      *
-     * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
+     * <p> Subclasses of {@code ClassLoader} are encouraged to override {@link
      * #findClass(String)}, rather than this method.  </p>
      *
      * <p> Unless overridden, this method synchronizes on the result of
-     * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
+     * {@link #getClassLoadingLock getClassLoadingLock} method
      * during the entire class loading process.
      *
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
      * @param  resolve
-     *         If <tt>true</tt> then resolve the class
+     *         If {@code true} then resolve the class
      *
-     * @return  The resulting <tt>Class</tt> object
+     * @return  The resulting {@code Class} object
      *
      * @throws  ClassNotFoundException
      *          If the class could not be found
@@ -606,7 +606,7 @@
      * @return the lock for class loading operations
      *
      * @throws NullPointerException
-     *         If registered as parallel capable and <tt>className</tt> is null
+     *         If registered as parallel capable and {@code className} is null
      *
      * @see #loadClass(String, boolean)
      *
@@ -667,14 +667,14 @@
      * Finds the class with the specified <a href="#name">binary name</a>.
      * This method should be overridden by class loader implementations that
      * follow the delegation model for loading classes, and will be invoked by
-     * the {@link #loadClass <tt>loadClass</tt>} method after checking the
+     * the {@link #loadClass loadClass} method after checking the
      * parent class loader for the requested class.  The default implementation
-     * throws a <tt>ClassNotFoundException</tt>.
+     * throws a {@code ClassNotFoundException}.
      *
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
-     * @return  The resulting <tt>Class</tt> object
+     * @return  The resulting {@code Class} object
      *
      * @throws  ClassNotFoundException
      *          If the class could not be found
@@ -722,32 +722,32 @@
 
 
     /**
-     * Converts an array of bytes into an instance of class <tt>Class</tt>.
-     * Before the <tt>Class</tt> can be used it must be resolved.  This method
+     * Converts an array of bytes into an instance of class {@code Class}.
+     * Before the {@code Class} can be used it must be resolved.  This method
      * is deprecated in favor of the version that takes a <a
      * href="#name">binary name</a> as its first argument, and is more secure.
      *
      * @param  b
      *         The bytes that make up the class data.  The bytes in positions
-     *         <tt>off</tt> through <tt>off+len-1</tt> should have the format
+     *         {@code off} through {@code off+len-1} should have the format
      *         of a valid class file as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *
      * @param  off
-     *         The start offset in <tt>b</tt> of the class data
+     *         The start offset in {@code b} of the class data
      *
      * @param  len
      *         The length of the class data
      *
-     * @return  The <tt>Class</tt> object that was created from the specified
+     * @return  The {@code Class} object that was created from the specified
      *          class data
      *
      * @throws  ClassFormatError
      *          If the data did not contain a valid class
      *
      * @throws  IndexOutOfBoundsException
-     *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
-     *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
+     *          If either {@code off} or {@code len} is negative, or if
+     *          {@code off+len} is greater than {@code b.length}.
      *
      * @throws  SecurityException
      *          If an attempt is made to add this class to a package that
@@ -994,11 +994,11 @@
      * #defineClass(String, byte[], int, int, ProtectionDomain)}.
      *
      * <p> An invocation of this method of the form
-     * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
-     * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
+     * <i>cl</i>{@code .defineClass(}<i>name</i>{@code ,}
+     * <i>bBuffer</i>{@code ,} <i>pd</i>{@code )} yields exactly the same
      * result as the statements
      *
-     *<p> <tt>
+     *<p> <code>
      * ...<br>
      * byte[] temp = new byte[bBuffer.{@link
      * java.nio.ByteBuffer#remaining remaining}()];<br>
@@ -1007,16 +1007,16 @@
      *     return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
      * cl.defineClass}(name, temp, 0,
      * temp.length, pd);<br>
-     * </tt></p>
+     * </code></p>
      *
      * @param  name
      *         The expected <a href="#name">binary name</a>. of the class, or
-     *         <tt>null</tt> if not known
+     *         {@code null} if not known
      *
      * @param  b
      *         The bytes that make up the class data. The bytes from positions
-     *         <tt>b.position()</tt> through <tt>b.position() + b.limit() -1
-     *         </tt> should have the format of a valid class file as defined by
+     *         {@code b.position()} through {@code b.position() + b.limit() -1
+     *         } should have the format of a valid class file as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *
      * @param  protectionDomain
@@ -1158,7 +1158,7 @@
 
     /**
      * Links the specified class.  This (misleadingly named) method may be
-     * used by a class loader to link a class.  If the class <tt>c</tt> has
+     * used by a class loader to link a class.  If the class {@code c} has
      * already been linked, then this method simply returns. Otherwise, the
      * class is linked as described in the "Execution" chapter of
      * <cite>The Java&trade; Language Specification</cite>.
@@ -1167,7 +1167,7 @@
      *         The class to link
      *
      * @throws  NullPointerException
-     *          If <tt>c</tt> is <tt>null</tt>.
+     *          If {@code c} is {@code null}.
      *
      * @see  #defineClass(String, byte[], int, int)
      */
@@ -1182,16 +1182,16 @@
      * loading it if necessary.
      *
      * <p> This method loads the class through the system class loader (see
-     * {@link #getSystemClassLoader()}).  The <tt>Class</tt> object returned
-     * might have more than one <tt>ClassLoader</tt> associated with it.
-     * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method,
+     * {@link #getSystemClassLoader()}).  The {@code Class} object returned
+     * might have more than one {@code ClassLoader} associated with it.
+     * Subclasses of {@code ClassLoader} need not usually invoke this method,
      * because most class loaders need to override just {@link
      * #findClass(String)}.  </p>
      *
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
-     * @return  The <tt>Class</tt> object for the specified <tt>name</tt>
+     * @return  The {@code Class} object for the specified {@code name}
      *
      * @throws  ClassNotFoundException
      *          If the class could not be found
@@ -1222,12 +1222,12 @@
      * Returns the class with the given <a href="#name">binary name</a> if this
      * loader has been recorded by the Java virtual machine as an initiating
      * loader of a class with that <a href="#name">binary name</a>.  Otherwise
-     * <tt>null</tt> is returned.
+     * {@code null} is returned.
      *
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
-     * @return  The <tt>Class</tt> object, or <tt>null</tt> if the class has
+     * @return  The {@code Class} object, or {@code null} if the class has
      *          not been loaded
      *
      * @since  1.1
@@ -1245,7 +1245,7 @@
      * class.
      *
      * @param  c
-     *         The <tt>Class</tt> object
+     *         The {@code Class} object
      *
      * @param  signers
      *         The signers for the class
@@ -1306,11 +1306,11 @@
      * (images, audio, text, etc) that can be accessed by class code in a way
      * that is independent of the location of the code.
      *
-     * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
+     * <p> The name of a resource is a '{@code /}'-separated path name that
      * identifies the resource.
      *
      * <p> This method will first search the parent class loader for the
-     * resource; if the parent is <tt>null</tt> the path of the class loader
+     * resource; if the parent is {@code null} the path of the class loader
      * built-in to the virtual machine is searched.  That failing, this method
      * will invoke {@link #findResource(String)} to find the resource.  </p>
      *
@@ -1362,7 +1362,7 @@
      * (images, audio, text, etc) that can be accessed by class code in a way
      * that is independent of the location of the code.
      *
-     * <p> The name of a resource is a <tt>/</tt>-separated path name that
+     * <p> The name of a resource is a {@code /}-separated path name that
      * identifies the resource.
      *
      * <p> The delegation order for searching is described in the documentation
@@ -1389,7 +1389,7 @@
      * @param  name
      *         The resource name
      *
-     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
+     * @return  An enumeration of {@link java.net.URL URL} objects for
      *          the resource. If no resources could  be found, the enumeration
      *          will be empty. Resources for which a {@code URL} cannot be
      *          constructed, are in package that is not opened unconditionally,
@@ -1505,7 +1505,7 @@
     }
 
     /**
-     * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
+     * Returns an enumeration of {@link java.net.URL URL} objects
      * representing all the resources with the given name. Class loader
      * implementations should override this method to specify where to load
      * resources from.
@@ -1520,7 +1520,7 @@
      * @param  name
      *         The resource name
      *
-     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
+     * @return  An enumeration of {@link java.net.URL URL} objects for
      *          the resource. If no resources could  be found, the enumeration
      *          will be empty. Resources for which a {@code URL} cannot be
      *          constructed, are in a package that is not opened unconditionally,
@@ -1594,7 +1594,7 @@
      * @param  name
      *         The resource name
      *
-     * @return  A {@link java.net.URL <tt>URL</tt>} to the resource; {@code
+     * @return  A {@link java.net.URL URL} to the resource; {@code
      *          null} if the resource could not be found, a URL could not be
      *          constructed to locate the resource, the resource is in a package
      *          that is not opened unconditionally or access to the resource is
@@ -1609,8 +1609,8 @@
     /**
      * Finds all resources of the specified name from the search path used to
      * load classes.  The resources thus found are returned as an
-     * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
-     * java.net.URL <tt>URL</tt>} objects.
+     * {@link java.util.Enumeration Enumeration} of {@link
+     * java.net.URL URL} objects.
      *
      * <p> The search order is described in the documentation for {@link
      * #getSystemResource(String)}.  </p>
@@ -1625,7 +1625,7 @@
      * @param  name
      *         The resource name
      *
-     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
+     * @return  An enumeration of {@link java.net.URL URL} objects for
      *          the resource. If no resources could  be found, the enumeration
      *          will be empty. Resources for which a {@code URL} cannot be
      *          constructed, are in a package that is not opened unconditionally,
@@ -1714,11 +1714,11 @@
 
     /**
      * Returns the parent class loader for delegation. Some implementations may
-     * use <tt>null</tt> to represent the bootstrap class loader. This method
-     * will return <tt>null</tt> in such implementations if this class loader's
+     * use {@code null} to represent the bootstrap class loader. This method
+     * will return {@code null} in such implementations if this class loader's
      * parent is the bootstrap class loader.
      *
-     * @return  The parent <tt>ClassLoader</tt>
+     * @return  The parent {@code ClassLoader}
      *
      * @throws  SecurityException
      *          If a security manager is present, and the caller's class loader
@@ -1785,7 +1785,7 @@
 
     /**
      * Returns the system class loader for delegation.  This is the default
-     * delegation parent for new <tt>ClassLoader</tt> instances, and is
+     * delegation parent for new {@code ClassLoader} instances, and is
      * typically the class loader used to start the application.
      *
      * <p> This method is first invoked early in the runtime's startup
@@ -1797,12 +1797,12 @@
      * <p> The default system class loader is an implementation-dependent
      * instance of this class.
      *
-     * <p> If the system property "<tt>java.system.class.loader</tt>" is defined
+     * <p> If the system property "{@code java.system.class.loader}" is defined
      * when this method is first invoked then the value of that property is
      * taken to be the name of a class that will be returned as the system
      * class loader.  The class is loaded using the default system class loader
      * and must define a public constructor that takes a single parameter of
-     * type <tt>ClassLoader</tt> which is used as the delegation parent.  An
+     * type {@code ClassLoader} which is used as the delegation parent.  An
      * instance is then created using this constructor with the default system
      * class loader as the parameter.  The resulting class loader is defined
      * to be the system class loader. During construction, the class loader
@@ -1825,7 +1825,7 @@
      * the application module path then the class path defaults to
      * the current working directory.
      *
-     * @return  The system <tt>ClassLoader</tt> for delegation
+     * @return  The system {@code ClassLoader} for delegation
      *
      * @throws  SecurityException
      *          If a security manager is present, and the caller's class loader
@@ -1835,11 +1835,11 @@
      *
      * @throws  IllegalStateException
      *          If invoked recursively during the construction of the class
-     *          loader specified by the "<tt>java.system.class.loader</tt>"
+     *          loader specified by the "{@code java.system.class.loader}"
      *          property.
      *
      * @throws  Error
-     *          If the system property "<tt>java.system.class.loader</tt>"
+     *          If the system property "{@code java.system.class.loader}"
      *          is defined but the named class could not be loaded, the
      *          provider class does not define the required constructor, or an
      *          exception is thrown by that constructor when it is invoked. The
@@ -2249,9 +2249,9 @@
     /**
      * Returns the absolute path name of a native library.  The VM invokes this
      * method to locate the native libraries that belong to classes loaded with
-     * this class loader. If this method returns <tt>null</tt>, the VM
+     * this class loader. If this method returns {@code null}, the VM
      * searches the library along the path specified as the
-     * "<tt>java.library.path</tt>" property.
+     * "{@code java.library.path}" property.
      *
      * @param  libname
      *         The library name
@@ -2270,12 +2270,12 @@
     /**
      * The inner class NativeLibrary denotes a loaded native library instance.
      * Every classloader contains a vector of loaded native libraries in the
-     * private field <tt>nativeLibraries</tt>.  The native libraries loaded
-     * into the system are entered into the <tt>systemNativeLibraries</tt>
+     * private field {@code nativeLibraries}.  The native libraries loaded
+     * into the system are entered into the {@code systemNativeLibraries}
      * vector.
      *
      * <p> Every native library requires a particular version of JNI. This is
-     * denoted by the private <tt>jniVersion</tt> field.  This field is set by
+     * denoted by the private {@code jniVersion} field.  This field is set by
      * the VM when it loads the library, and used by the VM to pass the correct
      * version of JNI to the native methods.  </p>
      *
@@ -2592,8 +2592,8 @@
      * #setClassAssertionStatus(String, boolean)}.
      *
      * @param  enabled
-     *         <tt>true</tt> if classes loaded by this class loader will
-     *         henceforth have assertions enabled by default, <tt>false</tt>
+     *         {@code true} if classes loaded by this class loader will
+     *         henceforth have assertions enabled by default, {@code false}
      *         if they will have assertions disabled by default.
      *
      * @since  1.4
@@ -2614,16 +2614,16 @@
      * any of its "subpackages".
      *
      * <p> A subpackage of a package named p is any package whose name begins
-     * with "<tt>p.</tt>".  For example, <tt>javax.swing.text</tt> is a
-     * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and
-     * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>.
+     * with "{@code p.}".  For example, {@code javax.swing.text} is a
+     * subpackage of {@code javax.swing}, and both {@code java.util} and
+     * {@code java.lang.reflect} are subpackages of {@code java}.
      *
      * <p> In the event that multiple package defaults apply to a given class,
      * the package default pertaining to the most specific package takes
-     * precedence over the others.  For example, if <tt>javax.lang</tt> and
-     * <tt>javax.lang.reflect</tt> both have package defaults associated with
+     * precedence over the others.  For example, if {@code javax.lang} and
+     * {@code javax.lang.reflect} both have package defaults associated with
      * them, the latter package default applies to classes in
-     * <tt>javax.lang.reflect</tt>.
+     * {@code javax.lang.reflect}.
      *
      * <p> Package defaults take precedence over the class loader's default
      * assertion status, and may be overridden on a per-class basis by invoking
@@ -2631,15 +2631,15 @@
      *
      * @param  packageName
      *         The name of the package whose package default assertion status
-     *         is to be set. A <tt>null</tt> value indicates the unnamed
+     *         is to be set. A {@code null} value indicates the unnamed
      *         package that is "current"
      *         (see section 7.4.2 of
      *         <cite>The Java&trade; Language Specification</cite>.)
      *
      * @param  enabled
-     *         <tt>true</tt> if classes loaded by this classloader and
+     *         {@code true} if classes loaded by this classloader and
      *         belonging to the named package or any of its subpackages will
-     *         have assertions enabled by default, <tt>false</tt> if they will
+     *         have assertions enabled by default, {@code false} if they will
      *         have assertions disabled by default.
      *
      * @since  1.4
@@ -2670,8 +2670,8 @@
      *         assertion status is to be set.
      *
      * @param  enabled
-     *         <tt>true</tt> if the named class is to have assertions
-     *         enabled when (and if) it is initialized, <tt>false</tt> if the
+     *         {@code true} if the named class is to have assertions
+     *         enabled when (and if) it is initialized, {@code false} if the
      *         class is to have assertions disabled.
      *
      * @since  1.4
@@ -2687,7 +2687,7 @@
 
     /**
      * Sets the default assertion status for this class loader to
-     * <tt>false</tt> and discards any package defaults or class assertion
+     * {@code false} and discards any package defaults or class assertion
      * status settings associated with the class loader.  This method is
      * provided so that class loaders can be made to ignore any command line or
      * persistent assertion status settings and "start with a clean slate."
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java	Wed Jul 05 22:42:01 2017 +0200
@@ -30,8 +30,10 @@
 import java.io.OutputStream;
 import java.security.PrivilegedAction;
 import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.Date;
 import java.util.Iterator;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
@@ -231,7 +233,7 @@
      */
     protected boolean allowUserInteraction = defaultAllowUserInteraction;
 
-    private static boolean defaultUseCaches = true;
+    private static volatile boolean defaultUseCaches = true;
 
    /**
      * If {@code true}, the protocol is allowed to use caching
@@ -243,12 +245,18 @@
      * <p>
      * Its default value is the value given in the last invocation of the
      * {@code setDefaultUseCaches} method.
+     * <p>
+     * The default setting may be overridden per protocol with
+     * {@link #setDefaultUseCaches(String,boolean)}.
      *
      * @see     java.net.URLConnection#setUseCaches(boolean)
      * @see     java.net.URLConnection#getUseCaches()
      * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
      */
-    protected boolean useCaches = defaultUseCaches;
+    protected boolean useCaches;
+
+    private static final ConcurrentHashMap<String,Boolean> defaultCaching =
+        new ConcurrentHashMap<>();
 
    /**
      * Some protocols support skipping the fetching of the object unless
@@ -460,6 +468,11 @@
      */
     protected URLConnection(URL url) {
         this.url = url;
+        if (url == null) {
+            this.useCaches = defaultUseCaches;
+        } else {
+            this.useCaches = getDefaultUseCaches(url.getProtocol());
+        }
     }
 
     /**
@@ -981,7 +994,8 @@
      * is true, the connection is allowed to use whatever caches it can.
      *  If false, caches are to be ignored.
      *  The default value comes from DefaultUseCaches, which defaults to
-     * true.
+     * true. A default value can also be set per-protocol using
+     * {@link #setDefaultUseCaches(String,boolean)}.
      *
      * @param usecaches a {@code boolean} indicating whether
      * or not to allow caching
@@ -1032,9 +1046,10 @@
      * Returns the default value of a {@code URLConnection}'s
      * {@code useCaches} flag.
      * <p>
-     * Ths default is "sticky", being a part of the static state of all
+     * This default is "sticky", being a part of the static state of all
      * URLConnections.  This flag applies to the next, and all following
-     * URLConnections that are created.
+     * URLConnections that are created. This default value can be over-ridden
+     * per protocol using {@link #setDefaultUseCaches(String,boolean)}
      *
      * @return  the default value of a {@code URLConnection}'s
      *          {@code useCaches} flag.
@@ -1046,7 +1061,8 @@
 
    /**
      * Sets the default value of the {@code useCaches} field to the
-     * specified value.
+     * specified value. This default value can be over-ridden
+     * per protocol using {@link #setDefaultUseCaches(String,boolean)}
      *
      * @param   defaultusecaches   the new value.
      * @see     #getDefaultUseCaches()
@@ -1055,6 +1071,43 @@
         defaultUseCaches = defaultusecaches;
     }
 
+   /**
+     * Sets the default value of the {@code useCaches} field for the named
+     * protocol to the given value. This value overrides any default setting
+     * set by {@link #setDefaultUseCaches(boolean)} for the given protocol.
+     * Successive calls to this method change the setting and affect the
+     * default value for all future connections of that protocol. The protocol
+     * name is case insensitive.
+     *
+     * @param   protocol the protocol to set the default for
+     * @param   defaultVal whether caching is enabled by default for the given protocol
+     * @since 9
+     */
+    public static void setDefaultUseCaches(String protocol, boolean defaultVal) {
+        protocol = protocol.toLowerCase(Locale.US);
+        defaultCaching.put(protocol, defaultVal);
+    }
+
+   /**
+     * Returns the default value of the {@code useCaches} flag for the given protocol. If
+     * {@link #setDefaultUseCaches(String,boolean)} was called for the given protocol,
+     * then that value is returned. Otherwise, if {@link #setDefaultUseCaches(boolean)}
+     * was called, then that value is returned. If neither method was called,
+     * the return value is {@code true}. The protocol name is case insensitive.
+     *
+     * @param protocol the protocol whose defaultUseCaches setting is required
+     * @return  the default value of the {@code useCaches} flag for the given protocol.
+     * @since 9
+     */
+    public static boolean getDefaultUseCaches(String protocol) {
+        Boolean protoDefault = defaultCaching.get(protocol.toLowerCase(Locale.US));
+        if (protoDefault != null) {
+            return protoDefault.booleanValue();
+        } else {
+            return defaultUseCaches;
+        }
+    }
+
     /**
      * Sets the general request property. If a property with the key already
      * exists, overwrite its value with the new value.
--- a/jdk/src/java.base/share/classes/java/util/Collections.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -4354,6 +4354,11 @@
         private Object readResolve() {
             return EMPTY_SET;
         }
+
+        @Override
+        public int hashCode() {
+            return 0;
+        }
     }
 
     /**
@@ -4786,6 +4791,10 @@
         public boolean removeIf(Predicate<? super E> filter) {
             throw new UnsupportedOperationException();
         }
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(element);
+        }
     }
 
     /**
@@ -4848,6 +4857,10 @@
         public Spliterator<E> spliterator() {
             return singletonSpliterator(element);
         }
+        @Override
+        public int hashCode() {
+            return 31 + Objects.hashCode(element);
+        }
     }
 
     /**
@@ -4970,6 +4983,11 @@
                 BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
             throw new UnsupportedOperationException();
         }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(k) ^ Objects.hashCode(v);
+        }
     }
 
     // Miscellaneous
--- a/jdk/src/java.base/share/classes/java/util/Date.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Date.java	Wed Jul 05 22:42:01 2017 +0200
@@ -82,17 +82,19 @@
  * well; for example, the time scale used by the satellite-based
  * global positioning system (GPS) is synchronized to UTC but is
  * <i>not</i> adjusted for leap seconds. An interesting source of
- * further information is the U.S. Naval Observatory, particularly
- * the Directorate of Time at:
+ * further information is the United States Naval Observatory (USNO):
  * <blockquote><pre>
- *     <a href="http://www.usno.navy.mil">http://www.usno.navy.mil</a>
+ *     <a href="http://www.usno.navy.mil/USNO">http://www.usno.navy.mil/USNO</a>
  * </pre></blockquote>
  * <p>
- * and their definitions of "Systems of Time" at:
+ * and the material regarding "Systems of Time" at:
  * <blockquote><pre>
  *     <a href="http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time">http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time</a>
  * </pre></blockquote>
  * <p>
+ * which has descriptions of various different time systems including
+ * UT, UT1, and UTC.
+ * <p>
  * In all methods of class {@code Date} that accept or return
  * year, month, date, hours, minutes, and seconds values, the
  * following representations are used:
--- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
+import jdk.internal.vm.annotation.Stable;
 
 /**
  * Container class for immutable collections. Not part of the public API.
@@ -105,6 +106,11 @@
             return null;                  // but the compiler doesn't know this
         }
 
+        @Override
+        public Iterator<E> iterator() {
+            return Collections.emptyIterator();
+        }
+
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
             throw new InvalidObjectException("not serial proxy");
         }
@@ -112,9 +118,26 @@
         private Object writeReplace() {
             return new CollSer(CollSer.IMM_LIST);
         }
+
+        @Override
+        public boolean contains(Object o) {
+            Objects.requireNonNull(o);
+            return false;
+        }
+
+        @Override
+        public boolean containsAll(Collection<?> o) {
+            return o.isEmpty(); // implicit nullcheck of o
+        }
+
+        @Override
+        public int hashCode() {
+            return 1;
+        }
     }
 
     static final class List1<E> extends AbstractImmutableList<E> {
+        @Stable
         private final E e0;
 
         List1(E e0) {
@@ -129,7 +152,6 @@
         @Override
         public E get(int index) {
             Objects.checkIndex(index, 1);
-            // assert index == 0
             return e0;
         }
 
@@ -140,10 +162,22 @@
         private Object writeReplace() {
             return new CollSer(CollSer.IMM_LIST, e0);
         }
+
+        @Override
+        public boolean contains(Object o) {
+            return o.equals(e0); // implicit nullcheck of o
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 + e0.hashCode();
+        }
     }
 
     static final class List2<E> extends AbstractImmutableList<E> {
+        @Stable
         private final E e0;
+        @Stable
         private final E e1;
 
         List2(E e0, E e1) {
@@ -166,6 +200,17 @@
             }
         }
 
+        @Override
+        public boolean contains(Object o) {
+            return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 31 + e0.hashCode();
+            return 31 * hash + e1.hashCode();
+        }
+
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
             throw new InvalidObjectException("not serial proxy");
         }
@@ -176,6 +221,7 @@
     }
 
     static final class ListN<E> extends AbstractImmutableList<E> {
+        @Stable
         private final E[] elements;
 
         @SafeVarargs
@@ -200,6 +246,25 @@
             return elements[index];
         }
 
+        @Override
+        public boolean contains(Object o) {
+            for (E e : elements) {
+                if (o.equals(e)) { // implicit nullcheck of o
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 1;
+            for (E e : elements) {
+                hash = 31 * hash + e.hashCode();
+            }
+            return hash;
+        }
+
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
             throw new InvalidObjectException("not serial proxy");
         }
@@ -238,7 +303,13 @@
 
         @Override
         public boolean contains(Object o) {
-            return super.contains(Objects.requireNonNull(o));
+            Objects.requireNonNull(o);
+            return false;
+        }
+
+        @Override
+        public boolean containsAll(Collection<?> o) {
+            return o.isEmpty(); // implicit nullcheck of o
         }
 
         @Override
@@ -253,9 +324,15 @@
         private Object writeReplace() {
             return new CollSer(CollSer.IMM_SET);
         }
+
+        @Override
+        public int hashCode() {
+            return 0;
+        }
     }
 
     static final class Set1<E> extends AbstractImmutableSet<E> {
+        @Stable
         private final E e0;
 
         Set1(E e0) {
@@ -269,7 +346,7 @@
 
         @Override
         public boolean contains(Object o) {
-            return super.contains(Objects.requireNonNull(o));
+            return o.equals(e0); // implicit nullcheck of o
         }
 
         @Override
@@ -284,17 +361,21 @@
         private Object writeReplace() {
             return new CollSer(CollSer.IMM_SET, e0);
         }
+
+        @Override
+        public int hashCode() {
+            return e0.hashCode();
+        }
     }
 
     static final class Set2<E> extends AbstractImmutableSet<E> {
-        private final E e0;
-        private final E e1;
+        @Stable
+        final E e0;
+        @Stable
+        final E e1;
 
         Set2(E e0, E e1) {
-            Objects.requireNonNull(e0);
-            Objects.requireNonNull(e1);
-
-            if (e0.equals(e1)) {
+            if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0
                 throw new IllegalArgumentException("duplicate element: " + e0);
             }
 
@@ -314,7 +395,12 @@
 
         @Override
         public boolean contains(Object o) {
-            return super.contains(Objects.requireNonNull(o));
+            return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
+        }
+
+        @Override
+        public int hashCode() {
+            return e0.hashCode() + e1.hashCode();
         }
 
         @Override
@@ -358,8 +444,10 @@
      * @param <E> the element type
      */
     static final class SetN<E> extends AbstractImmutableSet<E> {
-        private final E[] elements;
-        private final int size;
+        @Stable
+        final E[] elements;
+        @Stable
+        final int size;
 
         @SafeVarargs
         @SuppressWarnings("unchecked")
@@ -368,8 +456,8 @@
 
             elements = (E[])new Object[EXPAND_FACTOR * input.length];
             for (int i = 0; i < input.length; i++) {
-                E e = Objects.requireNonNull(input[i]);
-                int idx = probe(e);
+                E e = input[i];
+                int idx = probe(e); // implicit nullcheck of e
                 if (idx >= 0) {
                     throw new IllegalArgumentException("duplicate element: " + e);
                 } else {
@@ -385,8 +473,7 @@
 
         @Override
         public boolean contains(Object o) {
-            Objects.requireNonNull(o);
-            return probe(o) >= 0;
+            return probe(o) >= 0; // implicit nullcheck of o
         }
 
         @Override
@@ -414,8 +501,21 @@
             };
         }
 
+        @Override
+        public int hashCode() {
+            int h = 0;
+            for (E e : elements) {
+                if (e != null) {
+                    h += e.hashCode();
+                }
+            }
+            return h;
+        }
+
         // returns index at which element is present; or if absent,
-        // (-i - 1) where i is location where element should be inserted
+        // (-i - 1) where i is location where element should be inserted.
+        // Callers are relying on this method to perform an implicit nullcheck
+        // of pe
         private int probe(Object pe) {
             int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length);
             while (true) {
@@ -481,12 +581,14 @@
 
         @Override
         public boolean containsKey(Object o) {
-            return super.containsKey(Objects.requireNonNull(o));
+            Objects.requireNonNull(o);
+            return false;
         }
 
         @Override
         public boolean containsValue(Object o) {
-            return super.containsValue(Objects.requireNonNull(o));
+            Objects.requireNonNull(o);
+            return false;
         }
 
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -496,10 +598,17 @@
         private Object writeReplace() {
             return new CollSer(CollSer.IMM_MAP);
         }
+
+        @Override
+        public int hashCode() {
+            return 0;
+        }
     }
 
     static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
+        @Stable
         private final K k0;
+        @Stable
         private final V v0;
 
         Map1(K k0, V v0) {
@@ -514,12 +623,12 @@
 
         @Override
         public boolean containsKey(Object o) {
-            return super.containsKey(Objects.requireNonNull(o));
+            return o.equals(k0); // implicit nullcheck of o
         }
 
         @Override
         public boolean containsValue(Object o) {
-            return super.containsValue(Objects.requireNonNull(o));
+            return o.equals(v0); // implicit nullcheck of o
         }
 
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -529,6 +638,11 @@
         private Object writeReplace() {
             return new CollSer(CollSer.IMM_MAP, k0, v0);
         }
+
+        @Override
+        public int hashCode() {
+            return k0.hashCode() ^ v0.hashCode();
+        }
     }
 
     /**
@@ -541,12 +655,13 @@
      * @param <V> the value type
      */
     static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
-        private final Object[] table; // pairs of key, value
-        private final int size; // number of pairs
+        @Stable
+        final Object[] table; // pairs of key, value
+        @Stable
+        final int size; // number of pairs
 
         MapN(Object... input) {
-            Objects.requireNonNull(input);
-            if ((input.length & 1) != 0) {
+            if ((input.length & 1) != 0) { // implicit nullcheck of input
                 throw new InternalError("length is odd");
             }
             size = input.length >> 1;
@@ -573,12 +688,30 @@
 
         @Override
         public boolean containsKey(Object o) {
-            return probe(Objects.requireNonNull(o)) >= 0;
+            return probe(o) >= 0; // implicit nullcheck of o
         }
 
         @Override
         public boolean containsValue(Object o) {
-            return super.containsValue(Objects.requireNonNull(o));
+            for (int i = 1; i < table.length; i += 2) {
+                Object v = table[i];
+                if (v != null && o.equals(v)) { // implicit nullcheck of o
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 0;
+            for (int i = 0; i < table.length; i += 2) {
+                Object k = table[i];
+                if (k != null) {
+                    hash += k.hashCode() ^ table[i + 1].hashCode();
+                }
+            }
+            return hash;
         }
 
         @Override
@@ -638,7 +771,9 @@
         }
 
         // returns index at which the probe key is present; or if absent,
-        // (-i - 1) where i is location where element should be inserted
+        // (-i - 1) where i is location where element should be inserted.
+        // Callers are relying on this method to perform an implicit nullcheck
+        // of pk.
         private int probe(Object pk) {
             int idx = Math.floorMod(pk.hashCode() ^ SALT, table.length >> 1) << 1;
             while (true) {
--- a/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/KeyValueHolder.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package java.util;
 
+import jdk.internal.vm.annotation.Stable;
+
 /**
  * An immutable container for a key and a value, suitable for use
  * in creating and populating {@code Map} instances.
@@ -48,7 +50,9 @@
  * @since 9
  */
 final class KeyValueHolder<K,V> implements Map.Entry<K,V> {
+    @Stable
     final K key;
+    @Stable
     final V value;
 
     KeyValueHolder(K k, V v) {
--- a/jdk/src/java.base/share/classes/java/util/List.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/List.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1027,8 +1027,7 @@
     @SafeVarargs
     @SuppressWarnings("varargs")
     static <E> List<E> of(E... elements) {
-        Objects.requireNonNull(elements);
-        switch (elements.length) {
+        switch (elements.length) { // implicit null check of elements
             case 0:
                 return ImmutableCollections.List0.instance();
             case 1:
--- a/jdk/src/java.base/share/classes/java/util/Map.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Map.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1602,8 +1602,7 @@
     @SafeVarargs
     @SuppressWarnings("varargs")
     static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
-        Objects.requireNonNull(entries);
-        if (entries.length == 0) {
+        if (entries.length == 0) { // implicit null check of entries
             return ImmutableCollections.Map0.instance();
         } else if (entries.length == 1) {
             return new ImmutableCollections.Map1<>(entries[0].getKey(),
--- a/jdk/src/java.base/share/classes/java/util/Set.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Set.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -689,8 +689,7 @@
     @SafeVarargs
     @SuppressWarnings("varargs")
     static <E> Set<E> of(E... elements) {
-        Objects.requireNonNull(elements);
-        switch (elements.length) {
+        switch (elements.length) { // implicit null check of elements
             case 0:
                 return ImmutableCollections.Set0.instance();
             case 1:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.module;
+
+import java.io.PrintStream;
+import java.lang.module.Configuration;
+import java.lang.module.ResolvedModule;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import static java.util.stream.Collectors.*;
+
+/**
+ * A Builder to compute ModuleHashes from a given configuration
+ */
+public class ModuleHashesBuilder {
+    private final Configuration configuration;
+    private final Set<String> hashModuleCandidates;
+
+    /**
+     * Constructs a ModuleHashesBuilder that finds the packaged modules
+     * from the location of ModuleReference found from the given Configuration.
+     *
+     * @param config Configuration for building module hashes
+     * @param modules the candidate modules to be hashed
+     */
+    public ModuleHashesBuilder(Configuration config, Set<String> modules) {
+        this.configuration = config;
+        this.hashModuleCandidates = modules;
+    }
+
+    /**
+     * Returns a map of a module M to ModuleHashes for the modules
+     * that depend upon M directly or indirectly.
+     *
+     * The key for each entry in the returned map is a module M that has
+     * no outgoing edges to any of the candidate modules to be hashed
+     * i.e. M is a leaf node in a connected subgraph containing M and
+     * other candidate modules from the module graph filtering
+     * the outgoing edges from M to non-candidate modules.
+     */
+    public Map<String, ModuleHashes> computeHashes(Set<String> roots) {
+        // build a graph containing the the packaged modules and
+        // its transitive dependences matching --hash-modules
+        Graph.Builder<String> builder = new Graph.Builder<>();
+        Deque<ResolvedModule> deque = new ArrayDeque<>(configuration.modules());
+        Set<ResolvedModule> visited = new HashSet<>();
+        while (!deque.isEmpty()) {
+            ResolvedModule rm = deque.pop();
+            if (!visited.contains(rm)) {
+                visited.add(rm);
+                builder.addNode(rm.name());
+                for (ResolvedModule dm : rm.reads()) {
+                    if (!visited.contains(dm)) {
+                        deque.push(dm);
+                    }
+                    builder.addEdge(rm.name(), dm.name());
+                }
+            }
+        }
+
+        // each node in a transposed graph is a matching packaged module
+        // in which the hash of the modules that depend upon it is recorded
+        Graph<String> transposedGraph = builder.build().transpose();
+
+        // traverse the modules in topological order that will identify
+        // the modules to record the hashes - it is the first matching
+        // module and has not been hashed during the traversal.
+        Set<String> mods = new HashSet<>();
+        Map<String, ModuleHashes> hashes = new HashMap<>();
+        builder.build()
+               .orderedNodes()
+               .filter(mn -> roots.contains(mn) && !mods.contains(mn))
+               .forEach(mn -> {
+                   // Compute hashes of the modules that depend on mn directly and
+                   // indirectly excluding itself.
+                   Set<String> ns = transposedGraph.dfs(mn)
+                       .stream()
+                       .filter(n -> !n.equals(mn) && hashModuleCandidates.contains(n))
+                       .collect(toSet());
+                   mods.add(mn);
+                   mods.addAll(ns);
+
+                   if (!ns.isEmpty()) {
+                       Map<String, Path> moduleToPath = ns.stream()
+                           .collect(toMap(Function.identity(), this::moduleToPath));
+                       hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
+                   }
+               });
+        return hashes;
+    }
+
+    private Path moduleToPath(String name) {
+        ResolvedModule rm = configuration.findModule(name).orElseThrow(
+            () -> new InternalError("Selected module " + name + " not on module path"));
+
+        URI uri = rm.reference().location().get();
+        Path path = Paths.get(uri);
+        String fn = path.getFileName().toString();
+        if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
+            throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
+        }
+        return path;
+    }
+
+    /*
+     * Utilty class
+     */
+    static class Graph<T> {
+        private final Set<T> nodes;
+        private final Map<T, Set<T>> edges;
+
+        public Graph(Set<T> nodes, Map<T, Set<T>> edges) {
+            this.nodes = Collections.unmodifiableSet(nodes);
+            this.edges = Collections.unmodifiableMap(edges);
+        }
+
+        public Set<T> nodes() {
+            return nodes;
+        }
+
+        public Map<T, Set<T>> edges() {
+            return edges;
+        }
+
+        public Set<T> adjacentNodes(T u) {
+            return edges.get(u);
+        }
+
+        public boolean contains(T u) {
+            return nodes.contains(u);
+        }
+
+        /**
+         * Returns nodes sorted in topological order.
+         */
+        public Stream<T> orderedNodes() {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            return sorter.result.stream();
+        }
+
+        /**
+         * Traverse this graph and performs the given action in topological order
+         */
+        public void ordered(Consumer<T> action) {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            sorter.ordered(action);
+        }
+
+        /**
+         * Traverses this graph and performs the given action in reverse topological order
+         */
+        public void reverse(Consumer<T> action) {
+            TopoSorter<T> sorter = new TopoSorter<>(this);
+            sorter.reverse(action);
+        }
+
+        /**
+         * Returns a transposed graph from this graph
+         */
+        public Graph<T> transpose() {
+            Builder<T> builder = new Builder<>();
+            nodes.stream().forEach(builder::addNode);
+            // reverse edges
+            edges.keySet().forEach(u -> {
+                edges.get(u).stream()
+                    .forEach(v -> builder.addEdge(v, u));
+            });
+            return builder.build();
+        }
+
+        /**
+         * Returns all nodes reachable from the given root.
+         */
+        public Set<T> dfs(T root) {
+            return dfs(Set.of(root));
+        }
+
+        /**
+         * Returns all nodes reachable from the given set of roots.
+         */
+        public Set<T> dfs(Set<T> roots) {
+            Deque<T> deque = new LinkedList<>(roots);
+            Set<T> visited = new HashSet<>();
+            while (!deque.isEmpty()) {
+                T u = deque.pop();
+                if (!visited.contains(u)) {
+                    visited.add(u);
+                    if (contains(u)) {
+                        adjacentNodes(u).stream()
+                            .filter(v -> !visited.contains(v))
+                            .forEach(deque::push);
+                    }
+                }
+            }
+            return visited;
+        }
+
+        public void printGraph(PrintStream out) {
+            out.println("graph for " + nodes);
+            nodes.stream()
+                .forEach(u -> adjacentNodes(u).stream()
+                    .forEach(v -> out.format("  %s -> %s%n", u, v)));
+        }
+
+        static class Builder<T> {
+            final Set<T> nodes = new HashSet<>();
+            final Map<T, Set<T>> edges = new HashMap<>();
+
+            public void addNode(T node) {
+                if (nodes.contains(node)) {
+                    return;
+                }
+                nodes.add(node);
+                edges.computeIfAbsent(node, _e -> new HashSet<>());
+            }
+
+            public void addEdge(T u, T v) {
+                addNode(u);
+                addNode(v);
+                edges.get(u).add(v);
+            }
+
+            public Graph<T> build() {
+                return new Graph<T>(nodes, edges);
+            }
+        }
+    }
+
+    /**
+     * Topological sort
+     */
+    private static class TopoSorter<T> {
+        final Deque<T> result = new LinkedList<>();
+        final Deque<T> nodes;
+        final Graph<T> graph;
+
+        TopoSorter(Graph<T> graph) {
+            this.graph = graph;
+            this.nodes = new LinkedList<>(graph.nodes);
+            sort();
+        }
+
+        public void ordered(Consumer<T> action) {
+            result.iterator().forEachRemaining(action);
+        }
+
+        public void reverse(Consumer<T> action) {
+            result.descendingIterator().forEachRemaining(action);
+        }
+
+        private void sort() {
+            Deque<T> visited = new LinkedList<>();
+            Deque<T> done = new LinkedList<>();
+            T node;
+            while ((node = nodes.poll()) != null) {
+                if (!visited.contains(node)) {
+                    visit(node, visited, done);
+                }
+            }
+        }
+
+        private void visit(T node, Deque<T> visited, Deque<T> done) {
+            if (visited.contains(node)) {
+                if (!done.contains(node)) {
+                    throw new IllegalArgumentException("Cyclic detected: " +
+                        node + " " + graph.edges().get(node));
+                }
+                return;
+            }
+            visited.add(node);
+            graph.edges().get(node).stream()
+                .forEach(x -> visit(x, visited, done));
+            done.add(node);
+            result.addLast(node);
+        }
+    }
+}
--- a/jdk/src/java.base/share/native/libnet/net_util.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.c	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,10 +64,10 @@
     preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);
 
     /*
-       Since we have initialized and loaded the Socket library we will
-       check now to whether we have IPv6 on this platform and if the
-       supporting socket APIs are available
-    */
+     * Since we have initialized and loaded the socket library we will
+     * check now whether we have IPv6 on this platform and if the
+     * supporting socket APIs are available
+     */
     IPv6_available = IPv6_supported() & (!preferIPv4Stack);
 
     /* check if SO_REUSEPORT is supported on this platform */
@@ -120,16 +120,16 @@
     return JNI_TRUE;
 }
 
-int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
+jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) {
     jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
-    CHECK_NULL_RETURN(holder, -1);
+    CHECK_NULL_RETURN(holder, JNI_FALSE);
     return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID);
 }
 
-int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
+unsigned int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) {
     jobject holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID);
-    CHECK_NULL_RETURN(holder, -1);
-    return (*env)->GetIntField(env, holder, ia6_scopeidID);
+    CHECK_NULL_RETURN(holder, 0);
+    return (unsigned int)(*env)->GetIntField(env, holder, ia6_scopeidID);
 }
 
 jboolean setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) {
@@ -201,11 +201,10 @@
 }
 
 JNIEXPORT jobject JNICALL
-NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
+NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port) {
     jobject iaObj;
-    if (him->sa_family == AF_INET6) {
-        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-        jbyte *caddr = (jbyte *)&(him6->sin6_addr);
+    if (sa->sa.sa_family == AF_INET6) {
+        jbyte *caddr = (jbyte *)&sa->sa6.sin6_addr;
         if (NET_IsIPv4Mapped(caddr)) {
             int address;
             iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
@@ -214,42 +213,35 @@
             setInetAddress_addr(env, iaObj, address);
             setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
         } else {
-            jint scope;
             jboolean ret;
             iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
             CHECK_NULL_RETURN(iaObj, NULL);
-            ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
+            ret = setInet6Address_ipaddress(env, iaObj, (char *)&sa->sa6.sin6_addr);
             if (ret == JNI_FALSE)
                 return NULL;
             setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
-            scope = getScopeID(him);
-            setInet6Address_scopeid(env, iaObj, scope);
+            setInet6Address_scopeid(env, iaObj, sa->sa6.sin6_scope_id);
         }
-        *port = ntohs(him6->sin6_port);
+        *port = ntohs(sa->sa6.sin6_port);
     } else {
-        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
         iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
         CHECK_NULL_RETURN(iaObj, NULL);
         setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
-        setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
-        *port = ntohs(him4->sin_port);
+        setInetAddress_addr(env, iaObj, ntohl(sa->sa4.sin_addr.s_addr));
+        *port = ntohs(sa->sa4.sin_port);
     }
     return iaObj;
 }
 
-JNIEXPORT jint JNICALL
-NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
+JNIEXPORT jboolean JNICALL
+NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj)
 {
-    jint family = AF_INET;
-
-    family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
-        AF_INET : AF_INET6;
-    if (him->sa_family == AF_INET6) {
-        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-        jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
+    jint family = getInetAddress_family(env, iaObj) ==
+        java_net_InetAddress_IPv4 ? AF_INET : AF_INET6;
+    if (sa->sa.sa_family == AF_INET6) {
+        jbyte *caddrNew = (jbyte *)&sa->sa6.sin6_addr;
         if (NET_IsIPv4Mapped(caddrNew)) {
-            int addrNew;
-            int addrCur;
+            int addrNew, addrCur;
             if (family == AF_INET6) {
                 return JNI_FALSE;
             }
@@ -262,26 +254,24 @@
             }
         } else {
             jbyte caddrCur[16];
-            int scope;
-
             if (family == AF_INET) {
                 return JNI_FALSE;
             }
-            scope = getInet6Address_scopeid(env, iaObj);
             getInet6Address_ipaddress(env, iaObj, (char *)caddrCur);
-            if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
+            if (NET_IsEqual(caddrNew, caddrCur) &&
+                sa->sa6.sin6_scope_id == getInet6Address_scopeid(env, iaObj))
+            {
                 return JNI_TRUE;
             } else {
                 return JNI_FALSE;
             }
         }
     } else {
-        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
         int addrNew, addrCur;
         if (family != AF_INET) {
             return JNI_FALSE;
         }
-        addrNew = ntohl(him4->sin_addr.s_addr);
+        addrNew = ntohl(sa->sa4.sin_addr.s_addr);
         addrCur = getInetAddress_addr(env, iaObj);
         if (addrNew == addrCur) {
             return JNI_TRUE;
@@ -291,6 +281,15 @@
     }
 }
 
+JNIEXPORT jint JNICALL
+NET_GetPortFromSockaddr(SOCKETADDRESS *sa) {
+    if (sa->sa.sa_family == AF_INET6) {
+        return ntohs(sa->sa6.sin6_port);
+    } else {
+        return ntohs(sa->sa4.sin_port);
+    }
+}
+
 unsigned short
 in_cksum(unsigned short *addr, int len) {
     int nleft = len;
--- a/jdk/src/java.base/share/native/libnet/net_util.h	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.h	Wed Jul 05 22:42:01 2017 +0200
@@ -63,8 +63,8 @@
  */
 extern jobject getInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj);
 extern jboolean setInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj, jobject scopeifname);
-extern int getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj);
-extern int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj);
+extern jboolean getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj);
+extern unsigned int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj);
 extern jboolean setInet6Address_scopeid(JNIEnv *env, jobject ia6Obj, int scopeid);
 extern jboolean getInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *dest);
 extern jboolean setInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *address);
@@ -132,24 +132,41 @@
 
 JNIEXPORT jint JNICALL reuseport_available();
 
+/**
+ * This function will fill a SOCKETADDRESS structure from an InetAddress
+ * object.
+ *
+ * The parameter 'sa' must point to valid storage of size
+ * 'sizeof(SOCKETADDRESS)'.
+ *
+ * The parameter 'len' is a pointer to an int and is used for returning
+ * the actual sockaddr length, e.g. 'sizeof(struct sockaddr_in)' or
+ * 'sizeof(struct sockaddr_in6)'.
+ *
+ * If the type of the InetAddress object is IPv6, the function will fill a
+ * sockaddr_in6 structure. IPv6 must be available in that case, otherwise an
+ * exception is thrown.
+ * In the case of an IPv4 InetAddress, when IPv6 is available and
+ * v4MappedAddress is TRUE, this method will fill a sockaddr_in6 structure
+ * containing an IPv4 mapped IPv6 address. Otherwise a sockaddr_in
+ * structure will be filled.
+ */
 JNIEXPORT int JNICALL
 NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
-                          struct sockaddr *him, int *len,
+                          SOCKETADDRESS *sa, int *len,
                           jboolean v4MappedAddress);
 
 JNIEXPORT jobject JNICALL
-NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
+NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
 
 void platformInit();
 
 void parseExclusiveBindProperty(JNIEnv *env);
 
-void NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa);
 
-JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(struct sockaddr *him);
-
-JNIEXPORT jint JNICALL
-NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
+JNIEXPORT jboolean JNICALL
+NET_SockaddrEqualsInetAddress(JNIEnv *env, SOCKETADDRESS *sa, jobject iaObj);
 
 int NET_IsIPv4Mapped(jbyte* caddr);
 
@@ -172,7 +189,7 @@
 NET_SetSockOpt(int fd, int level, int opt, const void *arg, int len);
 
 JNIEXPORT int JNICALL
-NET_Bind(int fd, struct sockaddr *him, int len);
+NET_Bind(int fd, SOCKETADDRESS *sa, int len);
 
 JNIEXPORT int JNICALL
 NET_MapSocketOption(jint cmd, int *level, int *optname);
@@ -183,10 +200,6 @@
 JNIEXPORT jint JNICALL
 NET_EnableFastTcpLoopback(int fd);
 
-int getScopeID(struct sockaddr *);
-
-int cmpScopeID(unsigned int, struct sockaddr *);
-
 unsigned short in_cksum(unsigned short *addr, int len);
 
 jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -211,7 +211,8 @@
         {
             int port;
             int index = (family == AF_INET) ? i++ : j++;
-            jobject o = NET_SockaddrToInetAddress(env, iter->ifa_addr, &port);
+            jobject o = NET_SockaddrToInetAddress(env,
+                            (SOCKETADDRESS *)iter->ifa_addr, &port);
             if (!o) {
                 freeifaddrs(ifa);
                 if (!(*env)->ExceptionCheck(env))
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -791,7 +791,7 @@
     int sock;
 
     sock = openSocket(env, AF_INET);
-    if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+    if (sock < 0) {
         return NULL;
     }
 
@@ -809,7 +809,7 @@
     // so we have to call ipv6_available()
     if (ipv6_available()) {
         sock = openSocket(env, AF_INET6);
-        if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+        if (sock < 0) {
             freeif(ifs);
             return NULL;
         }
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -99,7 +99,7 @@
         CHECK_NULL_RETURN(i_class, NULL);
     }
 
-    return ( (*env)->NewObject(env, i_class, i_ctrID, i) );
+    return (*env)->NewObject(env, i_class, i_ctrID, i);
 }
 
 /*
@@ -118,10 +118,9 @@
         CHECK_NULL_RETURN(b_class, NULL);
     }
 
-    return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
+    return (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b != 0));
 }
 
-
 /*
  * Returns the fd for a PlainDatagramSocketImpl or -1
  * if closed.
@@ -134,7 +133,6 @@
     return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 }
 
-
 /*
  * Class:     java_net_PlainDatagramSocketImpl
  * Method:    init
@@ -166,7 +164,6 @@
     initInetAddressIDs(env);
     JNU_CHECK_EXCEPTION(env);
     Java_java_net_NetworkInterface_init(env, 0);
-
 }
 
 /*
@@ -176,13 +173,13 @@
  */
 JNIEXPORT void JNICALL
 Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
-                                           jint localport, jobject iaObj) {
+                                            jint localport, jobject iaObj) {
     /* fdObj is the FileDescriptor field on this */
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     /* fd is an int field on fdObj */
     int fd;
     int len = 0;
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
     socklen_t slen = sizeof(SOCKETADDRESS);
 
     if (IS_NULL(fdObj)) {
@@ -199,12 +196,13 @@
     }
 
     /* bind */
-    if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, &len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len,
+                                  JNI_TRUE) != 0) {
       return;
     }
-    setDefaultScopeID(env, &him.sa);
+    setDefaultScopeID(env, &sa.sa);
 
-    if (NET_Bind(fd, &him.sa, len) < 0)  {
+    if (NET_Bind(fd, &sa, len) < 0)  {
         if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
             errno == EPERM || errno == EACCES) {
             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
@@ -221,13 +219,13 @@
         /* Now that we're a connected socket, let's extract the port number
          * that the system chose for us and store it in the Socket object.
          */
-        if (getsockname(fd, &him.sa, &slen) == -1) {
+        if (getsockname(fd, &sa.sa, &slen) == -1) {
             JNU_ThrowByNameWithMessageAndLastError
                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return;
         }
 
-        localport = NET_GetPortFromSockaddr(&him.sa);
+        localport = NET_GetPortFromSockaddr(&sa);
 
         (*env)->SetIntField(env, this, pdsi_localPortID, localport);
     } else {
@@ -263,7 +261,8 @@
         return;
     }
 
-    if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr.sa, &len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr, &len,
+                                  JNI_TRUE) != 0) {
       return;
     }
 
@@ -290,6 +289,9 @@
 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
     SOCKETADDRESS addr;
     socklen_t len;
+#if defined(__linux__)
+    int localPort = 0;
+#endif
 #endif
 
     if (IS_NULL(fdObj)) {
@@ -298,32 +300,31 @@
     fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
 
 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
-        memset(&addr, 0, sizeof(addr));
-        if (ipv6_available()) {
-            addr.sa6.sin6_family = AF_UNSPEC;
-            len = sizeof(struct sockaddr_in6);
-        } else {
-            addr.sa4.sin_family = AF_UNSPEC;
-            len = sizeof(struct sockaddr_in);
-        }
-        NET_Connect(fd, &addr.sa, len);
+    memset(&addr, 0, sizeof(addr));
+    if (ipv6_available()) {
+        addr.sa6.sin6_family = AF_UNSPEC;
+        len = sizeof(struct sockaddr_in6);
+    } else {
+        addr.sa4.sin_family = AF_UNSPEC;
+        len = sizeof(struct sockaddr_in);
+    }
+    NET_Connect(fd, &addr.sa, len);
 
-#ifdef __linux__
-        int localPort = 0;
-        if (getsockname(fd, &addr.sa, &len) == -1)
-            return;
+#if defined(__linux__)
+    if (getsockname(fd, &addr.sa, &len) == -1)
+        return;
 
-        localPort = NET_GetPortFromSockaddr(&addr.sa);
-        if (localPort == 0) {
-            localPort = (*env)->GetIntField(env, this, pdsi_localPortID);
-            if (addr.sa.sa_family == AF_INET6) {
-                addr.sa6.sin6_port = htons(localPort);
-            } else {
-                addr.sa4.sin_port = htons(localPort);
-            }
+    localPort = NET_GetPortFromSockaddr(&addr);
+    if (localPort == 0) {
+        localPort = (*env)->GetIntField(env, this, pdsi_localPortID);
+        if (addr.sa.sa_family == AF_INET6) {
+            addr.sa6.sin6_port = htons(localPort);
+        } else {
+            addr.sa4.sin_port = htons(localPort);
+        }
 
-            NET_Bind(fd, &addr.sa, len);
-        }
+        NET_Bind(fd, &addr, len);
+    }
 
 #endif
 #else
@@ -355,8 +356,9 @@
     /* The fdObj'fd */
     jint fd;
 
-    SOCKETADDRESS rmtaddr, *rmtaddrP = &rmtaddr;
-    int len;
+    SOCKETADDRESS rmtaddr;
+    struct sockaddr *rmtaddrP = 0;
+    int len = 0;
 
     if (IS_NULL(fdObj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -382,15 +384,14 @@
     packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
     packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID);
 
-    if (connected) {
-        /* arg to NET_Sendto () null in this case */
-        len = 0;
-        rmtaddrP = 0;
-    } else {
+    // arg to NET_Sendto() null, if connected
+    if (!connected) {
         packetPort = (*env)->GetIntField(env, packet, dp_portID);
-        if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, &rmtaddr.sa, &len, JNI_TRUE) != 0) {
+        if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, &rmtaddr,
+                                      &len, JNI_TRUE) != 0) {
             return;
         }
+        rmtaddrP = &rmtaddr.sa;
     }
     setDefaultScopeID(env, &rmtaddr.sa);
 
@@ -427,7 +428,7 @@
     (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,
                                (jbyte *)fullPacket);
     if (trafficClass != 0 && ipv6_available()) {
-        NET_SetTrafficClass(&rmtaddr.sa, trafficClass);
+        NET_SetTrafficClass(&rmtaddr, trafficClass);
     }
 
     /*
@@ -437,8 +438,7 @@
      * ECONNREFUSED indicating that an ICMP port unreachable has
      * received.
      */
-    ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0,
-                     (struct sockaddr *)rmtaddrP, len);
+    ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0, rmtaddrP, len);
 
     if (ret < 0) {
         if (errno == ECONNREFUSED) {
@@ -510,7 +510,7 @@
 #ifdef __solaris__
         if (errno == ECONNREFUSED) {
             int orig_errno = errno;
-            (void) recv(fd, buf, 1, 0);
+            recv(fd, buf, 1, 0);
             errno = orig_errno;
         }
 #endif
@@ -528,7 +528,7 @@
         return 0;
     }
 
-    iaObj = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
+    iaObj = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
     family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
         AF_INET : AF_INET6;
     if (family == AF_INET) { /* this API can't handle IPV6 addresses */
@@ -676,18 +676,18 @@
          */
         packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
         if (packetAddress != NULL) {
-            if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr.sa, packetAddress)) {
+            if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr, packetAddress)) {
                 /* force a new InetAddress to be created */
                 packetAddress = NULL;
             }
         }
         if (packetAddress == NULL) {
-            packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
+            packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
             /* stuff the new Inetaddress in the packet */
             (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
         } else {
             /* only get the new port number */
-            port = NET_GetPortFromSockaddr(&rmtaddr.sa);
+            port = NET_GetPortFromSockaddr(&rmtaddr);
         }
         /* and fill in the data, remote address/port and such */
         (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
@@ -857,18 +857,19 @@
              */
             packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
             if (packetAddress != NULL) {
-                if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr.sa, packetAddress)) {
+                if (!NET_SockaddrEqualsInetAddress(env, &rmtaddr,
+                                                   packetAddress)) {
                     /* force a new InetAddress to be created */
                     packetAddress = NULL;
                 }
             }
             if (packetAddress == NULL) {
-                packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
+                packetAddress = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
                 /* stuff the new Inetaddress in the packet */
                 (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
             } else {
                 /* only get the new port number */
-                port = NET_GetPortFromSockaddr(&rmtaddr.sa);
+                port = NET_GetPortFromSockaddr(&rmtaddr);
             }
             /* and fill in the data, remote address/port and such */
             (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
@@ -1040,6 +1041,7 @@
     /*
      * We need an ipv4 address here
      */
+    in.s_addr = 0;
     for (i = 0; i < len; i++) {
         addr = (*env)->GetObjectArrayElement(env, addrArray, i);
         if (getInetAddress_family(env, addr) == java_net_InetAddress_IPv4) {
@@ -1049,7 +1051,7 @@
     }
 
     if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
-                   (const char*)&in, sizeof(in)) < 0) {
+                   (const char *)&in, sizeof(in)) < 0) {
         JNU_ThrowByNameWithMessageAndLastError
             (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
@@ -1670,17 +1672,17 @@
      */
     if (opt == java_net_SocketOptions_SO_BINDADDR) {
         /* find out local IP address */
-        SOCKETADDRESS him;
+        SOCKETADDRESS sa;
         socklen_t len = sizeof(SOCKETADDRESS);
         int port;
         jobject iaObj;
 
-        if (getsockname(fd, &him.sa, &len) == -1) {
+        if (getsockname(fd, &sa.sa, &len) == -1) {
             JNU_ThrowByNameWithMessageAndLastError
                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return NULL;
         }
-        iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+        iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
 
         return iaObj;
     }
@@ -1969,6 +1971,7 @@
                 mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
 #ifdef __linux__
                 mname.imr_address.s_addr = htonl(getInetAddress_addr(env, addr));
+                mname.imr_ifindex = 0;
 #else
                 mname.imr_interface.s_addr = htonl(getInetAddress_addr(env, addr));
 #endif
@@ -2023,7 +2026,7 @@
 
 #ifdef __linux__
                 mname.imr_address.s_addr = in.s_addr;
-
+                mname.imr_ifindex = 0;
 #else
                 mname.imr_interface.s_addr = in.s_addr;
 #endif
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -244,7 +244,7 @@
     /* fd is an int field on iaObj */
     jint fd;
 
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
     /* The result of the connection */
     int connect_rv = -1;
 
@@ -260,17 +260,18 @@
     }
 
     /* connect */
-    if (NET_InetAddressToSockaddr(env, iaObj, port, &him.sa, &len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
+                                  JNI_TRUE) != 0) {
         return;
     }
-    setDefaultScopeID(env, &him.sa);
+    setDefaultScopeID(env, &sa.sa);
 
     if (trafficClass != 0 && ipv6_available()) {
-        NET_SetTrafficClass(&him.sa, trafficClass);
+        NET_SetTrafficClass(&sa, trafficClass);
     }
 
     if (timeout <= 0) {
-        connect_rv = NET_Connect(fd, &him.sa, len);
+        connect_rv = NET_Connect(fd, &sa.sa, len);
 #ifdef __solaris__
         if (connect_rv == -1 && errno == EINPROGRESS ) {
 
@@ -319,7 +320,7 @@
         SET_NONBLOCKING(fd);
 
         /* no need to use NET_Connect as non-blocking */
-        connect_rv = connect(fd, &him.sa, len);
+        connect_rv = connect(fd, &sa.sa, len);
 
         /* connection not established immediately */
         if (connect_rv != 0) {
@@ -467,11 +468,11 @@
          * that the system chose for us and store it in the Socket object.
          */
         socklen_t slen = sizeof(SOCKETADDRESS);
-        if (getsockname(fd, &him.sa, &slen) == -1) {
+        if (getsockname(fd, &sa.sa, &slen) == -1) {
             JNU_ThrowByNameWithMessageAndLastError
                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
         } else {
-            localport = NET_GetPortFromSockaddr(&him.sa);
+            localport = NET_GetPortFromSockaddr(&sa);
             (*env)->SetIntField(env, this, psi_localportID, localport);
         }
     }
@@ -490,8 +491,8 @@
     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
     /* fd is an int field on fdObj */
     int fd;
-    int len;
-    SOCKETADDRESS him;
+    int len = 0;
+    SOCKETADDRESS sa;
 
     if (IS_NULL(fdObj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -506,13 +507,13 @@
     }
 
     /* bind */
-    if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa,
+    if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa,
                                   &len, JNI_TRUE) != 0) {
         return;
     }
-    setDefaultScopeID(env, &him.sa);
+    setDefaultScopeID(env, &sa.sa);
 
-    if (NET_Bind(fd, &him.sa, len) < 0) {
+    if (NET_Bind(fd, &sa, len) < 0) {
         if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
             errno == EPERM || errno == EACCES) {
             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
@@ -533,12 +534,12 @@
         /* Now that we're a connected socket, let's extract the port number
          * that the system chose for us and store it in the Socket object.
          */
-        if (getsockname(fd, &him.sa, &slen) == -1) {
+        if (getsockname(fd, &sa.sa, &slen) == -1) {
             JNU_ThrowByNameWithMessageAndLastError
                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return;
         }
-        localport = NET_GetPortFromSockaddr(&him.sa);
+        localport = NET_GetPortFromSockaddr(&sa);
         (*env)->SetIntField(env, this, psi_localportID, localport);
     } else {
         (*env)->SetIntField(env, this, psi_localportID, localport);
@@ -606,7 +607,7 @@
     /* accepted fd */
     jint newfd;
 
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
     socklen_t slen = sizeof(SOCKETADDRESS);
 
     if (IS_NULL(fdObj)) {
@@ -661,7 +662,7 @@
             return;
         }
 
-        newfd = NET_Accept(fd, &him.sa, &slen);
+        newfd = NET_Accept(fd, &sa.sa, &slen);
 
         /* connection accepted */
         if (newfd >= 0) {
@@ -709,7 +710,7 @@
     /*
      * fill up the remote peer port and address in the new socket structure.
      */
-    socketAddressObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+    socketAddressObj = NET_SockaddrToInetAddress(env, &sa, &port);
     if (socketAddressObj == NULL) {
         /* should be pending exception */
         close(newfd);
@@ -944,19 +945,19 @@
      * SO_BINDADDR isn't a socket option
      */
     if (cmd == java_net_SocketOptions_SO_BINDADDR) {
-        SOCKETADDRESS him;
+        SOCKETADDRESS sa;
         socklen_t len = sizeof(SOCKETADDRESS);
         int port;
         jobject iaObj;
         jclass iaCntrClass;
         jfieldID iaFieldID;
 
-        if (getsockname(fd, &him.sa, &len) < 0) {
+        if (getsockname(fd, &sa.sa, &len) < 0) {
             JNU_ThrowByNameWithMessageAndLastError
                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return -1;
         }
-        iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+        iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
         CHECK_NULL_RETURN(iaObj, -1);
 
         iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c	Wed Jul 05 22:42:01 2017 +0200
@@ -234,29 +234,6 @@
     }
     return kernelV24;
 }
-
-int getScopeID (struct sockaddr *him) {
-    struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
-    return hext->sin6_scope_id;
-}
-
-int cmpScopeID (unsigned int scope, struct sockaddr *him) {
-    struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
-    return hext->sin6_scope_id == scope;
-}
-
-#else
-
-int getScopeID (struct sockaddr *him) {
-    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-    return him6->sin6_scope_id;
-}
-
-int cmpScopeID (unsigned int scope, struct sockaddr *him) {
-    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-    return him6->sin6_scope_id == scope;
-}
-
 #endif
 
 void
@@ -775,30 +752,32 @@
     return 0;
 }
 
-/* In the case of an IPv4 Inetaddress this method will return an
- * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
- * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
-*/
+/**
+ * See net_util.h for documentation
+ */
 JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
-                          int *len, jboolean v4MappedAddress) {
-    jint family;
-    family = getInetAddress_family(env, iaObj);
-    /* needs work. 1. family 2. clean up him6 etc deallocate memory */
-    if (ipv6_available() && !(family == java_net_InetAddress_IPv4 &&
-                              v4MappedAddress == JNI_FALSE)) {
-        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+                          SOCKETADDRESS *sa, int *len,
+                          jboolean v4MappedAddress)
+{
+    jint family = getInetAddress_family(env, iaObj);
+    memset((char *)sa, 0, sizeof(SOCKETADDRESS));
+
+    if (ipv6_available() &&
+        !(family == java_net_InetAddress_IPv4 &&
+          v4MappedAddress == JNI_FALSE))
+    {
         jbyte caddr[16];
         jint address;
 
         if (family == java_net_InetAddress_IPv4) {
             // convert to IPv4-mapped address
-            memset((char *) caddr, 0, 16);
+            memset((char *)caddr, 0, 16);
             address = getInetAddress_addr(env, iaObj);
             if (address == INADDR_ANY) {
                 /* we would always prefer IPv6 wildcard address
-                   caddr[10] = 0xff;
-                   caddr[11] = 0xff; */
+                 * caddr[10] = 0xff;
+                 * caddr[11] = 0xff; */
             } else {
                 caddr[10] = 0xff;
                 caddr[11] = 0xff;
@@ -810,22 +789,19 @@
         } else {
             getInet6Address_ipaddress(env, iaObj, (char *)caddr);
         }
-        memset((char *)him6, 0, sizeof(struct sockaddr_in6));
-        him6->sin6_port = htons(port);
-        memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
-        him6->sin6_family = AF_INET6;
-        *len = sizeof(struct sockaddr_in6);
+        sa->sa6.sin6_port = htons(port);
+        memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr));
+        sa->sa6.sin6_family = AF_INET6;
+        if (len != NULL) {
+            *len = sizeof(struct sockaddr_in6);
+        }
 
-#if defined(_ALLBSD_SOURCE)
-// XXXBSD: should we do something with scope id here ? see below linux comment
-/* MMM: Come back to this! */
-#endif
-
+#ifdef __linux__
         /*
          * On Linux if we are connecting to a link-local address
          * we need to specify the interface in the scope_id (2.4 kernel only)
          *
-         * If the scope was cached the we use the cached value. If not cached but
+         * If the scope was cached then we use the cached value. If not cached but
          * specified in the Inet6Address we use that, but we first check if the
          * address needs to be routed via the loopback interface. In this case,
          * we override the specified value with that of the loopback interface.
@@ -833,9 +809,8 @@
          * we try to determine a value from the routing table. In all these
          * cases the used value is cached for further use.
          */
-#ifdef __linux__
-        if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {
-            int cached_scope_id = 0, scope_id = 0;
+        if (IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr)) {
+            unsigned int cached_scope_id = 0, scope_id = 0;
 
             if (ia6_cachedscopeidID) {
                 cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
@@ -850,7 +825,7 @@
                         /* check user-specified value for loopback case
                          * that needs to be overridden
                          */
-                        if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) {
+                        if (kernelIsV24() && needsLoopbackRoute(&sa->sa6.sin6_addr)) {
                             cached_scope_id = lo_scope_id;
                             (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
                         }
@@ -860,11 +835,11 @@
                          * try determine the appropriate interface.
                          */
                         if (kernelIsV24()) {
-                            cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr));
+                            cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr);
                         } else {
-                            cached_scope_id = getLocalScopeID((char *)&(him6->sin6_addr));
+                            cached_scope_id = getLocalScopeID((char *)&(sa->sa6.sin6_addr));
                             if (cached_scope_id == 0) {
-                                cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr));
+                                cached_scope_id = getDefaultIPv6Interface(&sa->sa6.sin6_addr);
                             }
                         }
                         (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
@@ -876,53 +851,37 @@
              * If we have a scope_id use the extended form
              * of sockaddr_in6.
              */
-
-            struct sockaddr_in6 *him6 =
-                    (struct sockaddr_in6 *)him;
-            him6->sin6_scope_id = cached_scope_id != 0 ?
-                                        cached_scope_id    : scope_id;
-            *len = sizeof(struct sockaddr_in6);
+            sa->sa6.sin6_scope_id = cached_scope_id == 0 ? scope_id : cached_scope_id;
         }
 #else
-        /* handle scope_id for solaris */
-
+        /* handle scope_id */
         if (family != java_net_InetAddress_IPv4) {
             if (ia6_scopeidID) {
-                him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
+                sa->sa6.sin6_scope_id = getInet6Address_scopeid(env, iaObj);
             }
         }
 #endif
     } else {
-        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
         jint address;
-        if (family == java_net_InetAddress_IPv6) {
+        if (family != java_net_InetAddress_IPv4) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
             return -1;
         }
-        memset((char *)him4, 0, sizeof(struct sockaddr_in));
         address = getInetAddress_addr(env, iaObj);
-        him4->sin_port = htons((short) port);
-        him4->sin_addr.s_addr = htonl(address);
-        him4->sin_family = AF_INET;
-        *len = sizeof(struct sockaddr_in);
+        sa->sa4.sin_port = htons(port);
+        sa->sa4.sin_addr.s_addr = htonl(address);
+        sa->sa4.sin_family = AF_INET;
+        if (len != NULL) {
+            *len = sizeof(struct sockaddr_in);
+        }
     }
     return 0;
 }
 
 void
-NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
-    if (him->sa_family == AF_INET6) {
-        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-        him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
-    }
-}
-
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him) {
-    if (him->sa_family == AF_INET6) {
-        return ntohs(((struct sockaddr_in6*)him)->sin6_port);
-    } else {
-        return ntohs(((struct sockaddr_in*)him)->sin_port);
+NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass) {
+    if (sa->sa.sa_family == AF_INET6) {
+        sa->sa6.sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
     }
 }
 
@@ -1488,7 +1447,7 @@
  *
  */
 int
-NET_Bind(int fd, struct sockaddr *him, int len)
+NET_Bind(int fd, SOCKETADDRESS *sa, int len)
 {
 #if defined(__solaris__)
     int level = -1;
@@ -1503,9 +1462,8 @@
      * ## When IPv6 is enabled this will be an IPv4-mapped
      * ## with family set to AF_INET6
      */
-    if (him->sa_family == AF_INET) {
-        struct sockaddr_in *sa = (struct sockaddr_in *)him;
-        if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
+    if (sa->sa.sa_family == AF_INET) {
+        if ((ntohl(sa->sa4.sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
             errno = EADDRNOTAVAIL;
             return -1;
         }
@@ -1524,8 +1482,9 @@
      */
     alen = sizeof(arg);
 
-    if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
-                   (char *)&arg, &alen) == 0) {
+    if (useExclBind ||
+        getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
+    {
         if (useExclBind || arg == 0) {
             /*
              * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
@@ -1533,8 +1492,8 @@
              * UDP_EXCLBIND
              */
             alen = sizeof(arg);
-            if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
-                           &alen) == 0) {
+            if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
+            {
                 if (arg == SOCK_STREAM) {
                     level = IPPROTO_TCP;
                     exclbind = TCP_EXCLBIND;
@@ -1545,14 +1504,13 @@
             }
 
             arg = 1;
-            setsockopt(fd, level, exclbind, (char *)&arg,
-                       sizeof(arg));
+            setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
         }
     }
 
 #endif
 
-    rv = bind(fd, him, len);
+    rv = bind(fd, &sa->sa, len);
 
 #if defined(__solaris__)
     if (rv < 0) {
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h	Wed Jul 05 22:42:01 2017 +0200
@@ -30,32 +30,6 @@
 #include <sys/poll.h>
 #include <sys/socket.h>
 
-int NET_Timeout(int s, long timeout);
-int NET_Timeout0(int s, long timeout, long currentTime);
-int NET_Read(int s, void* buf, size_t len);
-int NET_NonBlockingRead(int s, void* buf, size_t len);
-int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
-long NET_GetCurrentTime();
-int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
-                 struct sockaddr *from, socklen_t *fromlen);
-int NET_ReadV(int s, const struct iovec * vector, int count);
-int NET_Send(int s, void *msg, int len, unsigned int flags);
-int NET_SendTo(int s, const void *msg, int len,  unsigned  int
-               flags, const struct sockaddr *to, int tolen);
-int NET_Writev(int s, const struct iovec * vector, int count);
-int NET_Connect(int s, struct sockaddr *addr, int addrlen);
-int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
-int NET_SocketClose(int s);
-int NET_Dup2(int oldfd, int newfd);
-int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
-int NET_SocketAvailable(int s, jint *pbytes);
-
-void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
-                                               const char* hostname,
-                                               int gai_error);
-void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
-                                  const char *defaultDetail);
-
 /************************************************************************
  * Macros and constants
  */
@@ -91,9 +65,36 @@
 } SOCKETADDRESS;
 
 /************************************************************************
- *  Utilities
+ * Functions
  */
 
+int NET_Timeout(int s, long timeout);
+int NET_Timeout0(int s, long timeout, long currentTime);
+int NET_Read(int s, void* buf, size_t len);
+int NET_NonBlockingRead(int s, void* buf, size_t len);
+int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
+long NET_GetCurrentTime();
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+                 struct sockaddr *from, socklen_t *fromlen);
+int NET_ReadV(int s, const struct iovec * vector, int count);
+int NET_Send(int s, void *msg, int len, unsigned int flags);
+int NET_SendTo(int s, const void *msg, int len,  unsigned  int
+               flags, const struct sockaddr *to, int tolen);
+int NET_Writev(int s, const struct iovec * vector, int count);
+int NET_Connect(int s, struct sockaddr *addr, int addrlen);
+int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int NET_SocketClose(int s);
+int NET_Dup2(int oldfd, int newfd);
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+int NET_SocketAvailable(int s, jint *pbytes);
+
+void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
+                                               const char* hostname,
+                                               int gai_error);
+void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+                                  const char *defaultDetail);
+void NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass);
+
 #ifdef __linux__
 int kernelIsV24();
 int getDefaultIPv6Interface(struct in6_addr *target_addr);
--- a/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/DatagramChannelImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -181,11 +181,11 @@
      */
     senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
     if (senderAddr != NULL) {
-        if (!NET_SockaddrEqualsInetAddress(env, &sa.sa, senderAddr)) {
+        if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) {
             senderAddr = NULL;
         } else {
             jint port = (*env)->GetIntField(env, this, dci_senderPortID);
-            if (port != NET_GetPortFromSockaddr(&sa.sa)) {
+            if (port != NET_GetPortFromSockaddr(&sa)) {
                 senderAddr = NULL;
             }
         }
@@ -193,7 +193,7 @@
     if (senderAddr == NULL) {
         jobject isa = NULL;
         int port = 0;
-        jobject ia = NET_SockaddrToInetAddress(env, &sa.sa, &port);
+        jobject ia = NET_SockaddrToInetAddress(env, &sa, &port);
         if (ia != NULL) {
             isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
         }
@@ -201,7 +201,7 @@
 
         (*env)->SetObjectField(env, this, dci_senderAddrID, ia);
         (*env)->SetIntField(env, this, dci_senderPortID,
-                            NET_GetPortFromSockaddr(&sa.sa));
+                            NET_GetPortFromSockaddr(&sa));
         (*env)->SetObjectField(env, this, dci_senderID, isa);
     }
     return n;
@@ -215,14 +215,14 @@
     jint fd = fdval(env, fdo);
     void *buf = (void *)jlong_to_ptr(address);
     SOCKETADDRESS sa;
-    int sa_len = sizeof(SOCKETADDRESS);
+    int sa_len = 0;
     jint n = 0;
 
     if (len > MAX_PACKET_LEN) {
         len = MAX_PACKET_LEN;
     }
 
-    if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa.sa,
+    if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa,
                                   &sa_len, preferIPv6) != 0) {
       return IOS_THROWN;
     }
--- a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c	Wed Jul 05 22:42:01 2017 +0200
@@ -64,7 +64,7 @@
 
     if (getpeername(fd, &sa.sa, &len) == 0) {
         if (matchFamily(&sa.sa)) {
-            remote_ia = NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port);
+            remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
         }
     }
 
@@ -81,7 +81,7 @@
 
     if (getpeername(fd, &sa.sa, &len) == 0) {
         if (matchFamily(&sa.sa)) {
-            NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port);
+            NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
         }
     }
 
--- a/jdk/src/java.base/unix/native/libnio/ch/Net.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c	Wed Jul 05 22:42:01 2017 +0200
@@ -274,15 +274,15 @@
                           jboolean useExclBind, jobject iao, int port)
 {
     SOCKETADDRESS sa;
-    int sa_len = sizeof(SOCKETADDRESS);
+    int sa_len = 0;
     int rv = 0;
 
-    if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa, &sa_len,
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
                                   preferIPv6) != 0) {
         return;
     }
 
-    rv = NET_Bind(fdval(env, fdo), &sa.sa, sa_len);
+    rv = NET_Bind(fdval(env, fdo), &sa, sa_len);
     if (rv != 0) {
         handleSocketError(env, errno);
     }
@@ -300,10 +300,10 @@
                              jobject fdo, jobject iao, jint port)
 {
     SOCKETADDRESS sa;
-    int sa_len = sizeof(SOCKETADDRESS);
+    int sa_len = 0;
     int rv;
 
-    if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa, &sa_len,
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
                                   preferIPv6) != 0) {
         return IOS_THROWN;
     }
@@ -349,7 +349,7 @@
         return -1;
 #endif /* _ALLBSD_SOURCE */
     }
-    return NET_GetPortFromSockaddr(&sa.sa);
+    return NET_GetPortFromSockaddr(&sa);
 }
 
 JNIEXPORT jobject JNICALL
@@ -382,7 +382,7 @@
         return NULL;
 #endif /* _ALLBSD_SOURCE */
     }
-    return NET_SockaddrToInetAddress(env, &sa.sa, &port);
+    return NET_SockaddrToInetAddress(env, &sa, &port);
 }
 
 JNIEXPORT jint JNICALL
--- a/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -112,7 +112,7 @@
     }
 
     (*env)->SetIntField(env, newfdo, fd_fdID, newfd);
-    remote_ia = NET_SockaddrToInetAddress(env, &sa.sa, (int *)&remote_port);
+    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
     CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
     isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
     CHECK_NULL_RETURN(isa, IOS_THROWN);
--- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -233,11 +233,14 @@
         int childStart = 0;
         int parentEnd = pn;
 
+        boolean isDirectoryRelative =
+            pn == 2 && isLetter(parent.charAt(0)) && parent.charAt(1) == ':';
+
         if ((cn > 1) && (c.charAt(0) == slash)) {
             if (c.charAt(1) == slash) {
                 /* Drop prefix when child is a UNC pathname */
                 childStart = 2;
-            } else {
+            } else if (!isDirectoryRelative) {
                 /* Drop prefix when child is drive-relative */
                 childStart = 1;
 
@@ -254,7 +257,7 @@
 
         int strlen = parentEnd + cn - childStart;
         char[] theChars = null;
-        if (child.charAt(childStart) == slash) {
+        if (child.charAt(childStart) == slash || isDirectoryRelative) {
             theChars = new char[strlen];
             parent.getChars(0, parentEnd, theChars, 0);
             child.getChars(childStart, cn, theChars, parentEnd);
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -53,7 +53,7 @@
             break;
         }
         if (recvfrom(fd, buf, 1, MSG_PEEK,
-                         (struct sockaddr *)&rmtaddr, &addrlen) != SOCKET_ERROR) {
+                     &rmtaddr.sa, &addrlen) != SOCKET_ERROR) {
             break;
         }
         if (WSAGetLastError() != WSAECONNRESET) {
@@ -61,7 +61,7 @@
             break;
         }
 
-        recvfrom(fd, buf, 1, 0,  (struct sockaddr *)&rmtaddr, &addrlen);
+        recvfrom(fd, buf, 1, 0, &rmtaddr.sa, &addrlen);
         got_icmp = JNI_TRUE;
     }
 
@@ -134,14 +134,13 @@
 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) {
     SOCKETADDRESS sa;
-    int rv;
-    int sa_len = sizeof(sa);
+    int rv, sa_len = 0;
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
                                  &sa_len, JNI_TRUE) != 0) {
         return;
     }
-    rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
+    rv = NET_WinBind(fd, &sa, sa_len, exclBind);
 
     if (rv == SOCKET_ERROR) {
         if (WSAGetLastError() == WSAEACCES) {
@@ -159,17 +158,15 @@
 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect
   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
     SOCKETADDRESS sa;
-    int rv;
-    int sa_len = sizeof(sa);
+    int rv, sa_len = 0, t = TRUE;
     DWORD x1, x2; /* ignored result codes */
-    int t = TRUE;
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
                                    &sa_len, JNI_TRUE) != 0) {
         return;
     }
 
-    rv = connect(fd, (struct sockaddr *)&sa, sa_len);
+    rv = connect(fd, &sa.sa, sa_len);
     if (rv == SOCKET_ERROR) {
         NET_ThrowNew(env, WSAGetLastError(), "connect");
         return;
@@ -192,7 +189,7 @@
     int t = FALSE;
 
     memset(&sa, 0, sa_len);
-    connect(fd, (struct sockaddr *)&sa, sa_len);
+    connect(fd, &sa.sa, sa_len);
 
     /* see comment in socketCreate */
     WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
@@ -219,7 +216,7 @@
     SOCKETADDRESS sa;
     int len = sizeof(sa);
 
-    if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
         return -1;
     }
@@ -238,12 +235,12 @@
     jobject iaObj;
     int port;
 
-    if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
         NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
         return NULL;
     }
 
-    iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+    iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
     return iaObj;
 }
 
@@ -316,7 +313,7 @@
 
         /* receive the packet */
         rv = recvfrom(fd, fullPacket, packetBufferLen, flags,
-                    (struct sockaddr *)&sa, &sa_len);
+                      &sa.sa, &sa_len);
 
         if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
             /* An icmp port unreachable - we must receive this as Windows
@@ -383,15 +380,13 @@
          */
         packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID);
         if (packetAddress != NULL) {
-            if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa,
-                                               packetAddress)) {
+            if (!NET_SockaddrEqualsInetAddress(env, &sa, packetAddress)) {
                 /* force a new InetAddress to be created */
                 packetAddress = NULL;
             }
         }
         if (packetAddress == NULL) {
-            packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa,
-                                                      &port);
+            packetAddress = NET_SockaddrToInetAddress(env, &sa, &port);
             if (packetAddress != NULL) {
                 /* stuff the new Inetaddress into the packet */
                 (*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress);
@@ -422,20 +417,18 @@
   (JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length,
      jobject iaObj, jint port, jboolean connected) {
     SOCKETADDRESS sa;
-    int sa_len = sizeof(sa);
-    SOCKETADDRESS *sap = &sa;
+    int rv, sa_len = 0;
+    struct sockaddr *sap = 0;
     char BUF[MAX_BUFFER_LEN];
     char *fullPacket;
-    int rv;
 
-    if (connected) {
-        sap = 0; /* arg to sendto () null in this case */
-        sa_len = 0;
-    } else {
-        if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
-                                       &sa_len, JNI_TRUE) != 0) {
+    // if already connected, sap arg to sendto() is null
+    if (!connected) {
+        if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+                                      &sa_len, JNI_TRUE) != 0) {
             return;
         }
+        sap = &sa.sa;
     }
 
     if (length > MAX_BUFFER_LEN) {
@@ -456,7 +449,7 @@
 
     (*env)->GetByteArrayRegion(env, data, offset, length,
                                (jbyte *)fullPacket);
-    rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len);
+    rv = sendto(fd, fullPacket, length, 0, sap, sa_len);
     if (rv == SOCKET_ERROR) {
         if (rv == -1) {
             NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -89,15 +89,14 @@
    jboolean exclBind)
 {
     SOCKETADDRESS sa;
-    int rv;
-    int sa_len = sizeof(sa);
+    int rv, sa_len = 0;
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
-                                 &sa_len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+                                  &sa_len, JNI_TRUE) != 0) {
       return;
     }
 
-    rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
+    rv = NET_WinBind(fd, &sa, sa_len, exclBind);
 
     if (rv == SOCKET_ERROR)
         NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
@@ -111,15 +110,14 @@
 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
     SOCKETADDRESS sa;
-    int rv;
-    int sa_len = sizeof(sa);
+    int rv, sa_len = 0;
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa,
-                                 &sa_len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+                                  &sa_len, JNI_TRUE) != 0) {
       return -1;
     }
 
-    rv = connect(fd, (struct sockaddr *)&sa, sa_len);
+    rv = connect(fd, &sa.sa, sa_len);
     if (rv == SOCKET_ERROR) {
         int err = WSAGetLastError();
         if (err == WSAEWOULDBLOCK) {
@@ -217,7 +215,7 @@
     SOCKETADDRESS sa;
     int len = sizeof(sa);
 
-    if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
         if (WSAGetLastError() == WSAENOTSOCK) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                     "Socket closed");
@@ -243,11 +241,11 @@
     jclass iaContainerClass;
     jfieldID iaFieldID;
 
-    if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) {
+    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
         NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
         return;
     }
-    iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+    iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
     CHECK_NULL(iaObj);
 
     iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
@@ -283,7 +281,7 @@
     int len = sizeof(sa);
 
     memset((char *)&sa, 0, len);
-    newfd = accept(fd, (struct sockaddr *)&sa, &len);
+    newfd = accept(fd, &sa.sa, &len);
 
     if (newfd == INVALID_SOCKET) {
         if (WSAGetLastError() == -2) {
@@ -298,7 +296,7 @@
 
     SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
 
-    ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+    ia = NET_SockaddrToInetAddress(env, &sa, &port);
     isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
     (*env)->SetObjectArrayElement(env, isaa, 0, isa);
 
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -420,18 +420,13 @@
                                            jboolean exclBind) {
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
-
-    int fd, fd1 = -1, family;
     int ipv6_supported = ipv6_available();
-
+    int fd, fd1 = -1, lcladdrlen = 0;
     SOCKETADDRESS lcladdr;
-    int lcladdrlen = sizeof(SOCKETADDRESS);
-    int address;
 
-    memset((char *)&lcladdr, 0, sizeof(lcladdr));
-
-    family = getInetAddress_family(env, addressObj);
-    if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
+    if (getInetAddress_family(env, addressObj) == java_net_InetAddress_IPv6 &&
+        !ipv6_supported)
+    {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Protocol family not supported");
         return;
@@ -446,14 +441,13 @@
             fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
         }
     }
+
     if (IS_NULL(addressObj)) {
         JNU_ThrowNullPointerException(env, "argument address");
         return;
-    } else {
-        address = getInetAddress_addr(env, addressObj);
     }
 
-    if (NET_InetAddressToSockaddr(env, addressObj, port, &lcladdr.sa,
+    if (NET_InetAddressToSockaddr(env, addressObj, port, &lcladdr,
                                   &lcladdrlen, JNI_FALSE) != 0) {
         return;
     }
@@ -493,7 +487,7 @@
             return;
         }
     } else {
-        if (NET_WinBind(fd, &lcladdr.sa, lcladdrlen, exclBind) == -1) {
+        if (NET_WinBind(fd, &lcladdr, lcladdrlen, exclBind) == -1) {
             if (WSAGetLastError() == WSAEACCES) {
                 WSASetLastError(WSAEADDRINUSE);
             }
@@ -507,7 +501,7 @@
             NET_ThrowCurrent(env, "getsockname");
             return;
         }
-        port = ntohs((u_short) GET_PORT (&lcladdr));
+        port = ntohs((u_short)GET_PORT(&lcladdr));
     }
     (*env)->SetIntField(env, this, pdsi_localPortID, port);
 }
@@ -520,27 +514,25 @@
  */
 
 JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this,
-                                               jobject address, jint port) {
-    /* The object's field */
+Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0
+  (JNIEnv *env, jobject this, jobject address, jint port)
+{
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
-    /* The fdObj'fd */
-    jint fd=-1, fd1=-1, fdc;
-    /* The packetAddress address, family and port */
-    jint addr, family;
+    jint fd = -1, fd1 = -1, fdc, family;
     SOCKETADDRESS rmtaddr;
-    int rmtaddrlen;
-    int ipv6_supported = ipv6_available();
+    int rmtaddrlen = 0;
 
     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Socket closed");
         return;
     }
+
     if (!IS_NULL(fdObj)) {
         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
     }
+
     if (!IS_NULL(fd1Obj)) {
         fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
     }
@@ -550,10 +542,8 @@
         return;
     }
 
-    addr = getInetAddress_addr(env, address);
-
     family = getInetAddress_family(env, address);
-    if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
+    if (family == java_net_InetAddress_IPv6 && !ipv6_available()) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Protocol family not supported");
         return;
@@ -572,12 +562,12 @@
         res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
     }
 
-    if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr.sa,
+    if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr,
                                   &rmtaddrlen, JNI_FALSE) != 0) {
         return;
     }
 
-    if (connect(fdc, &rmtaddr.sa, sizeof(rmtaddr)) == -1) {
+    if (connect(fdc, &rmtaddr.sa, rmtaddrlen) == -1) {
         NET_ThrowCurrent(env, "connect");
         return;
     }
@@ -631,9 +621,9 @@
  * Signature: (Ljava/net/DatagramPacket;)V
  */
 JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
-                                           jobject packet) {
-
+Java_java_net_TwoStacksPlainDatagramSocketImpl_send
+  (JNIEnv *env, jobject this, jobject packet)
+{
     char BUF[MAX_BUFFER_LEN];
     char *fullPacket;
     jobject fdObj;
@@ -647,11 +637,10 @@
     jbyteArray packetBuffer;
     jboolean connected;
 
-    SOCKETADDRESS rmtaddr, *addrp = &rmtaddr;
+    SOCKETADDRESS rmtaddr;
+    struct sockaddr *addrp = 0;
     int addrlen = 0;
 
-    memset((char *)&rmtaddr, 0, sizeof(rmtaddr));
-
     if (IS_NULL(packet)) {
         JNU_ThrowNullPointerException(env, "null packet");
         return;
@@ -696,14 +685,13 @@
         packetBufferLen = MAX_PACKET_LEN;
     }
 
-    if (connected) {
-        addrp = 0; /* arg to sendto () null in this case */
-        addrlen = 0;
-    } else {
-        if (NET_InetAddressToSockaddr(env, iaObj, packetPort, &rmtaddr.sa,
+    // sockaddr arg to sendto() is null if already connected
+    if (!connected) {
+        if (NET_InetAddressToSockaddr(env, iaObj, packetPort, &rmtaddr,
                                       &addrlen, JNI_FALSE) != 0) {
             return;
         }
+        addrp = &rmtaddr.sa;
     }
 
     if (packetBufferLen > MAX_BUFFER_LEN) {
@@ -753,11 +741,12 @@
         fullPacket = &(BUF[0]);
     }
 
-    (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,
-                               (jbyte *)fullPacket);
-    if (sendto(fd, fullPacket, packetBufferLen, 0,
-               (struct sockaddr *)addrp, addrlen) == SOCKET_ERROR) {
-         NET_ThrowCurrent(env, "Datagram send failed");
+    (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset,
+                               packetBufferLen, (jbyte *)fullPacket);
+    if (sendto(fd, fullPacket, packetBufferLen, 0, addrp,
+               addrlen) == SOCKET_ERROR)
+    {
+        NET_ThrowCurrent(env, "Datagram send failed");
     }
 
     if (packetBufferLen > MAX_BUFFER_LEN) {
@@ -1147,14 +1136,14 @@
          */
         packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
         if (packetAddress != NULL) {
-            if (!NET_SockaddrEqualsInetAddress(env, &remote_addr.sa,
+            if (!NET_SockaddrEqualsInetAddress(env, &remote_addr,
                                                packetAddress)) {
                 /* force a new InetAddress to be created */
                 packetAddress = NULL;
             }
         }
         if (packetAddress == NULL) {
-            packetAddress = NET_SockaddrToInetAddress(env, &remote_addr.sa,
+            packetAddress = NET_SockaddrToInetAddress(env, &remote_addr,
                                                       &port);
             /* stuff the new Inetaddress in the packet */
             (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
@@ -1431,20 +1420,21 @@
          * can't update any existing InetAddress because it is immutable
          */
         packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
-
         if (packetAddress != NULL) {
-            if (!NET_SockaddrEqualsInetAddress(env, &remote_addr.sa, packetAddress)) {
+            if (!NET_SockaddrEqualsInetAddress(env, &remote_addr,
+                                               packetAddress)) {
                 /* force a new InetAddress to be created */
                 packetAddress = NULL;
             }
         }
         if (packetAddress == NULL) {
-            packetAddress = NET_SockaddrToInetAddress(env, &remote_addr.sa, &port);
+            packetAddress = NET_SockaddrToInetAddress(env, &remote_addr,
+                                                      &port);
             /* stuff the new Inetaddress in the packet */
             (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
         } else {
             /* only get the new port number */
-            port = NET_GetPortFromSockaddr(&remote_addr.sa);
+            port = NET_GetPortFromSockaddr(&remote_addr);
         }
         /* populate the packet */
         (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
@@ -1528,7 +1518,7 @@
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
     int ipv6_supported = ipv6_available();
-    int fd=-1, fd1=-1;
+    int fd = -1, fd1 = -1;
 
     if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) {
         return;
@@ -1799,7 +1789,7 @@
 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption
   (JNIEnv *env,jobject this, jint opt,jobject value)
 {
-    int fd=-1, fd1=-1;
+    int fd = -1, fd1 = -1;
     int levelv4 = 0, levelv6 = 0, optnamev4 = 0, optnamev6 = 0, optlen = 0;
     union {
         int i;
@@ -2167,7 +2157,7 @@
 Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption
   (JNIEnv *env, jobject this, jint opt)
 {
-    int fd=-1, fd1=-1;
+    int fd = -1, fd1 = -1;
     int level, optname, optlen;
     union {
         int i;
@@ -2255,7 +2245,7 @@
   (JNIEnv *env, jobject this, jint family)
 {
     int fd = -1, fd1 = -1;
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
     int len = 0;
     int port;
     jobject iaObj;
@@ -2288,12 +2278,12 @@
         return NULL;
     }
 
-    if (getsockname(fd, &him.sa, &len) == -1) {
+    if (getsockname(fd, &sa.sa, &len) == -1) {
         JNU_ThrowByNameWithMessageAndLastError
             (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
         return NULL;
     }
-    iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+    iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
 
     return iaObj;
 }
@@ -2430,7 +2420,7 @@
 
     int len, family;
     int ipv6_supported = ipv6_available();
-    int cmd ;
+    int cmd;
 
     memset((char *)&in, 0, sizeof(in));
     memset((char *)&name, 0, sizeof(name));
@@ -2452,7 +2442,7 @@
         return;
     }
 
-    if (NET_InetAddressToSockaddr(env, iaObj, 0, &name.sa, &len, JNI_FALSE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, 0, &name, &len, JNI_FALSE) != 0) {
       return;
     }
 
@@ -2473,7 +2463,7 @@
           return;
         }
         if (IS_NULL(niObj)) {
-            len = sizeof (in);
+            len = sizeof(in);
             if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
                            (char *)&in, &len) < 0) {
                 NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed");
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -175,8 +175,8 @@
  */
 JNIEXPORT void JNICALL
 Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
-                                            jobject iaObj, jint port,
-                                            jint timeout)
+                                                     jobject iaObj, jint port,
+                                                     jint timeout)
 {
     jint localport = (*env)->GetIntField(env, this, psi_localportID);
 
@@ -193,11 +193,11 @@
     jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
     jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
 
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
 
     /* The result of the connection */
     int connect_res;
-    memset((char *)&him, 0, sizeof(him));
+    memset((char *)&sa, 0, sizeof(sa));
 
     if (!IS_NULL(fdObj)) {
         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
@@ -212,11 +212,12 @@
         return;
     }
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, &him.sa, &len, JNI_FALSE) != 0) {
-      return;
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
+                                  JNI_FALSE) != 0) {
+        return;
     }
 
-    family = him.sa.sa_family;
+    family = sa.sa.sa_family;
     if (family == AF_INET6) {
         if (!ipv6_supported) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -248,7 +249,7 @@
     (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
 
     if (timeout <= 0) {
-        connect_res = connect(fd, &him.sa, sizeof(SOCKETADDRESS));
+        connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
         if (connect_res == SOCKET_ERROR) {
             connect_res = WSAGetLastError();
         }
@@ -261,7 +262,7 @@
         ioctlsocket(fd, FIONBIO, &optval);
 
         /* initiate the connect */
-        connect_res = connect(fd, &him.sa, sizeof(SOCKETADDRESS));
+        connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
         if (connect_res == SOCKET_ERROR) {
             if (WSAGetLastError() != WSAEWOULDBLOCK) {
                 connect_res = WSAGetLastError();
@@ -362,7 +363,7 @@
          */
         u_short port;
         int len = sizeof(SOCKETADDRESS);
-        if (getsockname(fd, &him.sa, &len) == -1) {
+        if (getsockname(fd, &sa.sa, &len) == -1) {
             if (WSAGetLastError() == WSAENOTSOCK) {
                 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                                 "Socket closed");
@@ -371,7 +372,7 @@
             }
             return;
         }
-        port = ntohs((u_short)GET_PORT(&him));
+        port = ntohs((u_short)GET_PORT(&sa));
         (*env)->SetIntField(env, this, psi_localportID, (int) port);
     }
 }
@@ -396,7 +397,7 @@
     int family;
     int rv;
 
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
 
     fdObj = (*env)->GetObjectField(env, this, psi_fdID);
     fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
@@ -424,13 +425,13 @@
         return;
     }
 
-    if (NET_InetAddressToSockaddr(env, iaObj, localport, &him.sa, &len,
+    if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa, &len,
                                   JNI_FALSE) != 0) {
         return;
     }
     if (ipv6_supported) {
         struct ipv6bind v6bind;
-        v6bind.addr = &him;
+        v6bind.addr = &sa.sa;
         v6bind.ipv4_fd = fd;
         v6bind.ipv6_fd = fd1;
         rv = NET_BindV6(&v6bind, exclBind);
@@ -462,7 +463,7 @@
             (*env)->SetObjectField(env, this, psi_fd1ID, NULL);
         }
     } else {
-        rv = NET_WinBind(fd, &him.sa, len, exclBind);
+        rv = NET_WinBind(fd, &sa, len, exclBind);
     }
 
     if (rv == -1) {
@@ -481,11 +482,11 @@
         int len = sizeof(SOCKETADDRESS);
         u_short port;
 
-        if (getsockname(him.sa.sa_family == AF_INET ? fd: fd1, &him.sa, &len) == -1) {
+        if (getsockname(sa.sa.sa_family == AF_INET ? fd : fd1, &sa.sa, &len) == -1) {
             NET_ThrowCurrent(env, "getsockname in plain socketBind");
             return;
         }
-        port = ntohs((u_short) GET_PORT (&him));
+        port = ntohs((u_short) GET_PORT (&sa));
 
         (*env)->SetIntField(env, this, psi_localportID, (int)port);
     } else {
@@ -529,7 +530,7 @@
         JNU_ThrowNullPointerException(env, "socket address");
         return;
     }
-    if (NET_InetAddressToSockaddr(env, address, 0, &addr.sa, &addrlen,
+    if (NET_InetAddressToSockaddr(env, address, 0, &addr, &addrlen,
                                   JNI_FALSE) != 0) {
         return;
     }
@@ -585,7 +586,7 @@
     /* the fd int field on fdObj */
     jint fd=-1, fd1=-1;
 
-    SOCKETADDRESS him;
+    SOCKETADDRESS sa;
     jint len;
 
     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
@@ -676,7 +677,7 @@
             }
         }
     }
-    fd = accept(fd, &him.sa, &len);
+    fd = accept(fd, &sa.sa, &len);
     if (fd < 0) {
         /* REMIND: SOCKET CLOSED PROBLEM */
         if (fd == -2) {
@@ -691,7 +692,7 @@
     SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
     (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
 
-    if (him.sa.sa_family == AF_INET) {
+    if (sa.sa.sa_family == AF_INET) {
         if (inet4Cls == NULL) {
             jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
             if (c != NULL) {
@@ -717,7 +718,7 @@
             return;
         }
 
-        setInetAddress_addr(env, socketAddressObj, ntohl(him.sa4.sin_addr.s_addr));
+        setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
         setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
         (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
     } else {
@@ -743,14 +744,14 @@
             NET_SocketClose(fd);
             return;
         }
-        setInet6Address_ipaddress(env, socketAddressObj, (char *)&him.sa6.sin6_addr);
+        setInet6Address_ipaddress(env, socketAddressObj, (char *)&sa.sa6.sin6_addr);
         setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
-        setInet6Address_scopeid(env, socketAddressObj, him.sa6.sin6_scope_id);
+        setInet6Address_scopeid(env, socketAddressObj, sa.sa6.sin6_scope_id);
 
     }
     /* fields common to AF_INET and AF_INET6 */
 
-    port = ntohs ((u_short) GET_PORT (&him));
+    port = ntohs ((u_short)GET_PORT(&sa));
     (*env)->SetIntField(env, socket, psi_portID, (int)port);
     port = (*env)->GetIntField(env, this, psi_localportID);
     (*env)->SetIntField(env, socket, psi_localportID, port);
@@ -1025,14 +1026,14 @@
      * SO_BINDADDR isn't a socket option
      */
     if (opt == java_net_SocketOptions_SO_BINDADDR) {
-        SOCKETADDRESS him;
+        SOCKETADDRESS sa;
         int len = sizeof(SOCKETADDRESS);
         int port;
         jobject iaObj;
         jclass iaCntrClass;
         jfieldID iaFieldID;
 
-        memset((char *)&him, 0, len);
+        memset((char *)&sa, 0, len);
 
         if (fd == -1) {
             /* must be an IPV6 only socket. Case where both sockets are != -1
@@ -1041,12 +1042,12 @@
             fd = getFD1 (env, this);
         }
 
-        if (getsockname(fd, &him.sa, &len) < 0) {
+        if (getsockname(fd, &sa.sa, &len) < 0) {
             JNU_ThrowByNameWithMessageAndLastError
                 (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
             return -1;
         }
-        iaObj = NET_SockaddrToInetAddress(env, &him.sa, &port);
+        iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
         CHECK_NULL_RETURN(iaObj, -1);
 
         iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c	Wed Jul 05 22:42:01 2017 +0200
@@ -488,10 +488,10 @@
  * Should be only called by the wrapper method NET_WinBind
  */
 JNIEXPORT int JNICALL
-NET_Bind(int s, struct sockaddr *him, int len)
+NET_Bind(int s, SOCKETADDRESS *sa, int len)
 {
     int rv = 0;
-    rv = bind(s, him, len);
+    rv = bind(s, &sa->sa, len);
 
     if (rv == SOCKET_ERROR) {
         /*
@@ -511,11 +511,11 @@
  * if required, and then calls NET_BIND
  */
 JNIEXPORT int JNICALL
-NET_WinBind(int s, struct sockaddr *him, int len, jboolean exclBind)
+NET_WinBind(int s, SOCKETADDRESS *sa, int len, jboolean exclBind)
 {
     if (exclBind == JNI_TRUE)
         setExclusiveBind(s);
-    return NET_Bind(s, him, len);
+    return NET_Bind(s, sa, len);
 }
 
 JNIEXPORT int JNICALL
@@ -677,8 +677,8 @@
     if (family == AF_INET && (b->addr->sa4.sin_addr.s_addr != INADDR_ANY)) {
         /* bind to v4 only */
         int ret;
-        ret = NET_WinBind((int)b->ipv4_fd, (struct sockaddr *)b->addr,
-                                sizeof(SOCKETADDRESS), exclBind);
+        ret = NET_WinBind((int)b->ipv4_fd, b->addr,
+                          sizeof(SOCKETADDRESS), exclBind);
         if (ret == SOCKET_ERROR) {
             CLOSE_SOCKETS_AND_RETURN;
         }
@@ -689,7 +689,7 @@
     if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->sa6.sin6_addr))) {
         /* bind to v6 only */
         int ret;
-        ret = NET_WinBind((int)b->ipv6_fd, (struct sockaddr *)b->addr,
+        ret = NET_WinBind((int)b->ipv6_fd, b->addr,
                           sizeof(SOCKETADDRESS), exclBind);
         if (ret == SOCKET_ERROR) {
             CLOSE_SOCKETS_AND_RETURN;
@@ -719,7 +719,7 @@
         oaddr.sa4.sin_addr.s_addr = INADDR_ANY;
     }
 
-    rv = NET_WinBind(fd, (struct sockaddr *)b->addr, sizeof(SOCKETADDRESS), exclBind);
+    rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind);
     if (rv == SOCKET_ERROR) {
         CLOSE_SOCKETS_AND_RETURN;
     }
@@ -731,7 +731,7 @@
     }
     bound_port = GET_PORT (b->addr);
     SET_PORT (&oaddr, bound_port);
-    if ((rv = NET_WinBind(ofd, &oaddr.sa,
+    if ((rv = NET_WinBind(ofd, &oaddr,
                           sizeof(SOCKETADDRESS), exclBind)) == SOCKET_ERROR) {
         int retries;
         int sotype, arglen=sizeof(sotype);
@@ -768,7 +768,7 @@
 
             /* bind random port on first socket */
             SET_PORT (&oaddr, 0);
-            rv = NET_WinBind(ofd, &oaddr.sa, sizeof(SOCKETADDRESS), exclBind);
+            rv = NET_WinBind(ofd, &oaddr, sizeof(SOCKETADDRESS), exclBind);
             if (rv == SOCKET_ERROR) {
                 CLOSE_SOCKETS_AND_RETURN;
             }
@@ -784,8 +784,7 @@
             }
             bound_port = GET_PORT (&oaddr);
             SET_PORT (b->addr, bound_port);
-            rv = NET_WinBind(fd, (struct sockaddr *)b->addr,
-                             sizeof(SOCKETADDRESS), exclBind);
+            rv = NET_WinBind(fd, b->addr, sizeof(SOCKETADDRESS), exclBind);
 
             if (rv != SOCKET_ERROR) {
                 if (family == AF_INET) {
@@ -853,31 +852,33 @@
     return result == SOCKET_ERROR ? WSAGetLastError() : 0;
 }
 
-/* If address types is IPv6, then IPv6 must be available. Otherwise
- * no address can be generated. In the case of an IPv4 Inetaddress this
- * method will return an IPv4 mapped address where IPv6 is available and
- * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in
- * structure for an IPv4 InetAddress.
-*/
+/**
+ * See net_util.h for documentation
+ */
 JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
-                          int *len, jboolean v4MappedAddress) {
-    jint family, iafam;
-    iafam = getInetAddress_family(env, iaObj);
-    family = (iafam == java_net_InetAddress_IPv4)? AF_INET : AF_INET6;
-    if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) {
-        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+                          SOCKETADDRESS *sa, int *len,
+                          jboolean v4MappedAddress)
+{
+    jint family = getInetAddress_family(env, iaObj);
+    memset((char *)sa, 0, sizeof(SOCKETADDRESS));
+
+    if (ipv6_available() &&
+        !(family == java_net_InetAddress_IPv4 &&
+          v4MappedAddress == JNI_FALSE))
+    {
         jbyte caddr[16];
-        jint address, scopeid = 0;
-        jint cached_scope_id = 0;
+        jint address;
+        unsigned int scopeid = 0, cached_scope_id = 0;
 
-        if (family == AF_INET) { /* will convert to IPv4-mapped address */
-            memset((char *) caddr, 0, 16);
+        if (family == java_net_InetAddress_IPv4) {
+            // convert to IPv4-mapped address
+            memset((char *)caddr, 0, 16);
             address = getInetAddress_addr(env, iaObj);
             if (address == INADDR_ANY) {
                 /* we would always prefer IPv6 wildcard address
-                caddr[10] = 0xff;
-                caddr[11] = 0xff; */
+                 * caddr[10] = 0xff;
+                 * caddr[11] = 0xff; */
             } else {
                 caddr[10] = 0xff;
                 caddr[11] = 0xff;
@@ -889,46 +890,39 @@
         } else {
             getInet6Address_ipaddress(env, iaObj, (char *)caddr);
             scopeid = getInet6Address_scopeid(env, iaObj);
-            cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
+            cached_scope_id = (unsigned int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
         }
-
-        memset((char *)him6, 0, sizeof(struct sockaddr_in6));
-        him6->sin6_port = (u_short) htons((u_short)port);
-        memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
-        him6->sin6_family = AF_INET6;
-        if ((family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL( &(him6->sin6_addr) )
-            && (!scopeid && !cached_scope_id)) {
-            cached_scope_id = getDefaultIPv6Interface(env, him6);
+        sa->sa6.sin6_port = (u_short)htons((u_short)port);
+        memcpy((void *)&sa->sa6.sin6_addr, caddr, sizeof(struct in6_addr));
+        sa->sa6.sin6_family = AF_INET6;
+        if ((family == java_net_InetAddress_IPv6) &&
+            IN6_IS_ADDR_LINKLOCAL(&sa->sa6.sin6_addr) &&
+            (!scopeid && !cached_scope_id))
+        {
+            cached_scope_id = getDefaultIPv6Interface(env, &sa->sa6);
             (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
         }
-        him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id;
-        *len = sizeof(struct sockaddr_in6) ;
+        sa->sa6.sin6_scope_id = scopeid == 0 ? cached_scope_id : scopeid;
+        if (len != NULL) {
+            *len = sizeof(struct sockaddr_in6);
+        }
     } else {
-        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
         jint address;
-        if (family != AF_INET) {
-          JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
-          return -1;
+        if (family != java_net_InetAddress_IPv4) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
+            return -1;
         }
-        memset((char *)him4, 0, sizeof(struct sockaddr_in));
         address = getInetAddress_addr(env, iaObj);
-        him4->sin_port = htons((short) port);
-        him4->sin_addr.s_addr = (u_long) htonl(address);
-        him4->sin_family = AF_INET;
-        *len = sizeof(struct sockaddr_in);
+        sa->sa4.sin_port = htons((short)port);
+        sa->sa4.sin_addr.s_addr = (u_long)htonl(address);
+        sa->sa4.sin_family = AF_INET;
+        if (len != NULL) {
+            *len = sizeof(struct sockaddr_in);
+        }
     }
     return 0;
 }
 
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him) {
-    if (him->sa_family == AF_INET6) {
-        return ntohs(((struct sockaddr_in6 *)him)->sin6_port);
-    } else {
-        return ntohs(((struct sockaddr_in *)him)->sin_port);
-    }
-}
-
 int
 NET_IsIPv4Mapped(jbyte* caddr) {
     int i;
@@ -961,16 +955,6 @@
     return 1;
 }
 
-int getScopeID(struct sockaddr *him) {
-    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-    return him6->sin6_scope_id;
-}
-
-int cmpScopeID(unsigned int scope, struct sockaddr *him) {
-    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-    return him6->sin6_scope_id == scope;
-}
-
 /**
  * Wrapper for select/poll with timeout on a single file descriptor.
  *
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h	Wed Jul 05 22:42:01 2017 +0200
@@ -121,7 +121,7 @@
 
 JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind *b, jboolean exclBind);
 
-JNIEXPORT int JNICALL NET_WinBind(int s, struct sockaddr *him, int len,
+JNIEXPORT int JNICALL NET_WinBind(int s, SOCKETADDRESS *sa, int len,
                                   jboolean exclBind);
 
 /* XP versions of the native routines */
--- a/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnio/ch/DatagramChannelImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -96,7 +96,7 @@
             break;
         }
         if (recvfrom(fd, buf, 1, MSG_PEEK,
-                     (struct sockaddr *)&sa, &addrlen) != SOCKET_ERROR) {
+                     &sa.sa, &addrlen) != SOCKET_ERROR) {
             break;
         }
         if (WSAGetLastError() != WSAECONNRESET) {
@@ -104,7 +104,7 @@
             break;
         }
 
-        recvfrom(fd, buf, 1, 0,  (struct sockaddr *)&sa, &addrlen);
+        recvfrom(fd, buf, 1, 0, &sa.sa, &addrlen);
         got_icmp = JNI_TRUE;
     }
 
@@ -122,7 +122,7 @@
 
     memset(&sa, 0, sa_len);
 
-    rv = connect((SOCKET)fd, (struct sockaddr *)&sa, sa_len);
+    rv = connect((SOCKET)fd, &sa.sa, sa_len);
     if (rv == SOCKET_ERROR) {
         handleSocketError(env, WSAGetLastError());
     } else {
@@ -153,7 +153,7 @@
                      (char *)buf,
                      len,
                      0,
-                     (struct sockaddr *)&sa,
+                     &sa.sa,
                      &sa_len);
 
         if (n == SOCKET_ERROR) {
@@ -182,12 +182,11 @@
      */
     senderAddr = (*env)->GetObjectField(env, this, dci_senderAddrID);
     if (senderAddr != NULL) {
-        if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa,
-                                           senderAddr)) {
+        if (!NET_SockaddrEqualsInetAddress(env, &sa, senderAddr)) {
             senderAddr = NULL;
         } else {
             jint port = (*env)->GetIntField(env, this, dci_senderPortID);
-            if (port != NET_GetPortFromSockaddr((struct sockaddr *)&sa)) {
+            if (port != NET_GetPortFromSockaddr(&sa)) {
                 senderAddr = NULL;
             }
         }
@@ -195,7 +194,7 @@
     if (senderAddr == NULL) {
         jobject isa = NULL;
         int port;
-        jobject ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+        jobject ia = NET_SockaddrToInetAddress(env, &sa, &port);
         if (ia != NULL) {
             isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
         }
@@ -204,7 +203,7 @@
         // update cachedSenderInetAddress/cachedSenderPort
         (*env)->SetObjectField(env, this, dci_senderAddrID, ia);
         (*env)->SetIntField(env, this, dci_senderPortID,
-                            NET_GetPortFromSockaddr((struct sockaddr *)&sa));
+                            NET_GetPortFromSockaddr(&sa));
         (*env)->SetObjectField(env, this, dci_senderID, isa);
     }
     return n;
@@ -219,21 +218,15 @@
     jint fd = fdval(env, fdo);
     void *buf = (void *)jlong_to_ptr(address);
     SOCKETADDRESS sa;
-    int sa_len;
+    int sa_len = 0;
     jint rv = 0;
 
-    if (NET_InetAddressToSockaddr(env, destAddress, destPort,
-                                  (struct sockaddr *)&sa,
-                                   &sa_len, preferIPv6) != 0) {
+    if (NET_InetAddressToSockaddr(env, destAddress, destPort, &sa,
+                                  &sa_len, preferIPv6) != 0) {
       return IOS_THROWN;
     }
 
-    rv = sendto((SOCKET)fd,
-               buf,
-               len,
-               0,
-               (struct sockaddr *)&sa,
-               sa_len);
+    rv = sendto((SOCKET)fd, buf, len, 0, &sa.sa, sa_len);
     if (rv == SOCKET_ERROR) {
         int theErr = (jint)WSAGetLastError();
         if (theErr == WSAEWOULDBLOCK) {
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c	Wed Jul 05 22:42:01 2017 +0200
@@ -168,13 +168,13 @@
 {
     SOCKETADDRESS sa;
     int rv;
-    int sa_len;
+    int sa_len = 0;
 
-    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
-      return;
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
+        return;
     }
 
-    rv = NET_WinBind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len, isExclBind);
+    rv = NET_WinBind(fdval(env, fdo), &sa, sa_len, isExclBind);
     if (rv == SOCKET_ERROR)
         NET_ThrowNew(env, WSAGetLastError(), "bind");
 }
@@ -194,14 +194,14 @@
 {
     SOCKETADDRESS sa;
     int rv;
-    int sa_len;
+    int sa_len = 0;
     SOCKET s = (SOCKET)fdval(env, fdo);
 
-    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
         return IOS_THROWN;
     }
 
-    rv = connect(s, (struct sockaddr *)&sa, sa_len);
+    rv = connect(s, &sa.sa, sa_len);
     if (rv != 0) {
         int err = WSAGetLastError();
         if (err == WSAEINPROGRESS || err == WSAEWOULDBLOCK) {
@@ -226,7 +226,7 @@
     SOCKETADDRESS sa;
     int sa_len = sizeof(sa);
 
-    if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+    if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
         int error = WSAGetLastError();
         if (error == WSAEINVAL) {
             return 0;
@@ -234,7 +234,7 @@
         NET_ThrowNew(env, error, "getsockname");
         return IOS_THROWN;
     }
-    return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
+    return NET_GetPortFromSockaddr(&sa);
 }
 
 JNIEXPORT jobject JNICALL
@@ -244,11 +244,11 @@
     int sa_len = sizeof(sa);
     int port;
 
-    if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+    if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
         return NULL;
     }
-    return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+    return NET_SockaddrToInetAddress(env, &sa, &port);
 }
 
 JNIEXPORT jint JNICALL
@@ -257,7 +257,7 @@
     SOCKETADDRESS sa;
     int sa_len = sizeof(sa);
 
-    if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+    if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
         int error = WSAGetLastError();
         if (error == WSAEINVAL) {
             return 0;
@@ -265,7 +265,7 @@
         NET_ThrowNew(env, error, "getsockname");
         return IOS_THROWN;
     }
-    return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
+    return NET_GetPortFromSockaddr(&sa);
 }
 
 JNIEXPORT jobject JNICALL
@@ -275,11 +275,11 @@
     int sa_len = sizeof(sa);
     int port;
 
-    if (getpeername(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+    if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
         NET_ThrowNew(env, WSAGetLastError(), "getsockname");
         return NULL;
     }
-    return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
+    return NET_SockaddrToInetAddress(env, &sa, &port);
 }
 
 JNIEXPORT jint JNICALL
--- a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -95,7 +95,7 @@
     int addrlen = sizeof(sa);
 
     memset((char *)&sa, 0, sizeof(sa));
-    newfd = (jint)accept(ssfd, (struct sockaddr *)&sa, &addrlen);
+    newfd = (jint)accept(ssfd, &sa.sa, &addrlen);
     if (newfd == INVALID_SOCKET) {
         int theErr = (jint)WSAGetLastError();
         if (theErr == WSAEWOULDBLOCK) {
@@ -107,7 +107,7 @@
 
     SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
     (*env)->SetIntField(env, newfdo, fd_fdID, newfd);
-    remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port);
+    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
     CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
 
     isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
--- a/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.base/windows/native/libnio/ch/WindowsAsynchronousSocketChannelImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -88,26 +88,21 @@
 Java_sun_nio_ch_WindowsAsynchronousSocketChannelImpl_connect0(JNIEnv* env, jclass this,
     jlong socket, jboolean preferIPv6, jobject iao, jint port, jlong ov)
 {
-    SOCKET s = (SOCKET) jlong_to_ptr(socket);
-    OVERLAPPED* lpOverlapped = (OVERLAPPED*) jlong_to_ptr(ov);
+    SOCKET s = (SOCKET)jlong_to_ptr(socket);
+    OVERLAPPED *lpOverlapped = (OVERLAPPED *)jlong_to_ptr(ov);
 
     SOCKETADDRESS sa;
-    int sa_len;
+    int sa_len = 0;
     BOOL res;
 
-    if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, preferIPv6) != 0) {
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
+                                  preferIPv6) != 0) {
         return IOS_THROWN;
     }
 
     ZeroMemory((PVOID)lpOverlapped, sizeof(OVERLAPPED));
 
-    res = (*ConnectEx_func)(s,
-                            (struct sockaddr *)&sa,
-                            sa_len,
-                            NULL,
-                            0,
-                            NULL,
-                            lpOverlapped);
+    res = (*ConnectEx_func)(s, &sa.sa, sa_len, NULL, 0, NULL, lpOverlapped);
     if (res == 0) {
         int error = GetLastError();
         if (error == ERROR_IO_PENDING) {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 05 22:42:01 2017 +0200
@@ -231,6 +231,7 @@
     private boolean isFullScreenAnimationOn;
 
     private volatile boolean isInFullScreen;
+    private volatile boolean isIconifyAnimationActive;
 
     private Window target;
     private LWWindowPeer peer;
@@ -997,6 +998,9 @@
         if (peer != null) {
             peer.notifyIconify(iconify);
         }
+        if (iconify) {
+            isIconifyAnimationActive = false;
+        }
     }
 
     private void deliverZoom(final boolean isZoomed) {
@@ -1071,6 +1075,17 @@
         return true;
     }
 
+    private boolean isIconified() {
+        boolean isIconified = false;
+        if (target instanceof Frame) {
+            int state = ((Frame)target).getExtendedState();
+            if ((state & Frame.ICONIFIED) != 0) {
+                isIconified = true;
+            }
+        }
+        return isIconifyAnimationActive || isIconified;
+    }
+
     private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
         while (window != null) {
             if (this == window) {
@@ -1094,11 +1109,14 @@
         // the windows are ordered above their nearest owner; ancestors of the window,
         // which is going to become 'main window', are placed above their siblings.
         CPlatformWindow rootOwner = getRootOwner();
-        if (rootOwner.isVisible()) {
+        if (rootOwner.isVisible() && !rootOwner.isIconified()) {
             CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
         }
-        final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
-        orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+        // Do not order child windows of iconified owner.
+        if (!rootOwner.isIconified()) {
+            final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
+            orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+        }
     }
 
     private void orderAboveSiblingsImpl(Window[] windows) {
@@ -1109,10 +1127,12 @@
 
         // Go through the list of windows and perform ordering.
         for (Window w : windows) {
+            boolean iconified = false;
             final Object p = componentAccessor.getPeer(w);
             if (p instanceof LWWindowPeer) {
                 CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
-                if (pw != null && pw.isVisible()) {
+                iconified = isIconified();
+                if (pw != null && pw.isVisible() && !iconified) {
                     // If the window is one of ancestors of 'main window' or is going to become main by itself,
                     // the window should be ordered above its siblings; otherwise the window is just ordered
                     // above its nearest parent.
@@ -1125,10 +1145,13 @@
                     pw.applyWindowLevel(w);
                 }
             }
-            // Retrieve the child windows for each window from the list and store them for future use.
+            // Retrieve the child windows for each window from the list except iconified ones
+            // and store them for future use.
             // Note: we collect data about child windows even for invisible owners, since they may have
             // visible children.
-            childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
+            if (!iconified) {
+                childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
+            }
         }
         // If some windows, which have just been ordered, have any child windows, let's start new iteration
         // and order these child windows.
@@ -1149,6 +1172,10 @@
     //                          NATIVE CALLBACKS
     // ----------------------------------------------------------------------
 
+    private void windowWillMiniaturize() {
+        isIconifyAnimationActive = true;
+    }
+
     private void windowDidBecomeMain() {
         if (checkBlockingAndOrder()) return;
         // If it's not blocked, make sure it's above its siblings
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Wed Jul 05 22:42:01 2017 +0200
@@ -327,10 +327,43 @@
     return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]];
 }
 
+// Retrieves the list of possible window layers (levels)
++ (NSArray*) getWindowLayers {
+    static NSArray *windowLayers;
+    static dispatch_once_t token;
+
+    // Initialize the list of possible window layers
+    dispatch_once(&token, ^{
+        // The layers are ordered from front to back, (i.e. the toppest one is the first)
+        windowLayers = [NSArray arrayWithObjects:
+                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGPopUpMenuWindowLevelKey)],
+                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGFloatingWindowLevelKey)],
+                            [NSNumber numberWithInt:CGWindowLevelForKey(kCGNormalWindowLevelKey)],
+                            nil
+                        ];
+        [windowLayers retain];
+    });
+    return windowLayers;
+}
+
 // returns id for the topmost window under mouse
 + (NSInteger) getTopmostWindowUnderMouseID {
     NSInteger result = -1;
 
+    NSArray *windowLayers = [AWTWindow getWindowLayers];
+    // Looking for the window under mouse starting from the toppest layer
+    for (NSNumber *layer in windowLayers) {
+        result = [AWTWindow getTopmostWindowUnderMouseIDImpl:[layer integerValue]];
+        if (result != -1) {
+            break;
+        }
+    }
+    return result;
+}
+
++ (NSInteger) getTopmostWindowUnderMouseIDImpl:(NSInteger)windowLayer {
+    NSInteger result = -1;
+
     NSRect screenRect = [[NSScreen mainScreen] frame];
     NSPoint nsMouseLocation = [NSEvent mouseLocation];
     CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
@@ -339,7 +372,7 @@
 
     for (NSDictionary *window in windows) {
         NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue];
-        if (layer == 0) {
+        if (layer == windowLayer) {
             CGRect rect;
             CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect);
             if (CGRectContainsPoint(rect, cgMouseLocation)) {
@@ -639,6 +672,14 @@
 AWT_ASSERT_APPKIT_THREAD;
 
     self.isMinimizing = YES;
+
+    JNIEnv *env = [ThreadUtilities getJNIEnv];
+    jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
+    if (platformWindow != NULL) {
+        static JNF_MEMBER_CACHE(jm_windowWillMiniaturize, jc_CPlatformWindow, "windowWillMiniaturize", "()V");
+        JNFCallVoidMethod(env, platformWindow, jm_windowWillMiniaturize);
+        (*env)->DeleteLocalRef(env, platformWindow);
+    }
     // Excplicitly make myself a key window to avoid possible
     // negative visual effects during iconify operation
     [self.nsWindow makeKeyAndOrderFront:self.nsWindow];
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -730,18 +730,47 @@
             // to use it if the data layout is component type.
             if (iccProfileField != null
                     && itsRaw.getColorModel() instanceof ComponentColorModel) {
-                // Create a ColorSpace from the profile.
-                byte[] iccProfileValue = iccProfileField.getAsBytes();
-                ICC_Profile iccProfile
-                        = ICC_Profile.getInstance(iccProfileValue);
-                ICC_ColorSpace iccColorSpace
-                        = new ICC_ColorSpace(iccProfile);
-
                 // Get the raw sample and color information.
                 ColorModel cmRaw = itsRaw.getColorModel();
                 ColorSpace csRaw = cmRaw.getColorSpace();
                 SampleModel smRaw = itsRaw.getSampleModel();
 
+                ColorSpace iccColorSpace = null;
+                try {
+                    // Create a ColorSpace from the profile.
+                    byte[] iccProfileValue = iccProfileField.getAsBytes();
+                    ICC_Profile iccProfile
+                        = ICC_Profile.getInstance(iccProfileValue);
+                    iccColorSpace = new ICC_ColorSpace(iccProfile);
+
+                    // Workaround for JDK-8145241: test a conversion and fall
+                    // back to a standard ColorSpace if it fails. This
+                    // workaround could be removed if JDK-8145241 is fixed.
+                    float[] rgb =
+                        iccColorSpace.toRGB(new float[] {1.0F, 1.0F, 1.0F});
+                } catch (Exception iccProfileException) {
+                    processWarningOccurred("Superseding bad ICC profile: "
+                        + iccProfileException.getMessage());
+
+                    if (iccColorSpace != null) {
+                        switch (iccColorSpace.getType()) {
+                            case ColorSpace.TYPE_GRAY:
+                                iccColorSpace =
+                                    ColorSpace.getInstance(ColorSpace.CS_GRAY);
+                                break;
+                            case ColorSpace.TYPE_RGB:
+                                iccColorSpace =
+                                    ColorSpace.getInstance(ColorSpace.CS_sRGB);
+                                break;
+                            default:
+                                iccColorSpace = csRaw;
+                                break;
+                        }
+                    } else {
+                        iccColorSpace = csRaw;
+                    }
+                }
+
                 // Get the number of samples per pixel and the number
                 // of color components.
                 int numBands = smRaw.getNumBands();
--- a/jdk/src/java.desktop/share/classes/java/beans/AppletInitializer.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/java/beans/AppletInitializer.java	Wed Jul 05 22:42:01 2017 +0200
@@ -30,21 +30,20 @@
 import java.beans.beancontext.BeanContext;
 
 /**
- * <p>
  * This interface is designed to work in collusion with java.beans.Beans.instantiate.
  * The interface is intended to provide mechanism to allow the proper
  * initialization of JavaBeans that are also Applets, during their
  * instantiation by java.beans.Beans.instantiate().
- * </p>
  *
  * @see java.beans.Beans#instantiate
  *
  * @since 1.2
  *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
-
-
-@SuppressWarnings("deprecation")
+@Deprecated(since = "9")
 public interface AppletInitializer {
 
     /**
@@ -74,7 +73,6 @@
      * @param bCtxt          The BeanContext intended for this Applet, or
      *                       null.
      */
-
     void initialize(Applet newAppletBean, BeanContext bCtxt);
 
     /**
@@ -86,6 +84,5 @@
      *
      * @param newApplet  The newly instantiated JavaBean
      */
-
     void activate(Applet newApplet);
 }
--- a/jdk/src/java.desktop/share/classes/java/beans/Beans.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/java/beans/Beans.java	Wed Jul 05 22:42:01 2017 +0200
@@ -97,8 +97,10 @@
      * @exception IOException if an I/O error occurs.
      * @since 1.2
      */
-
-    public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext) throws IOException, ClassNotFoundException {
+    @SuppressWarnings("deprecation")
+    public static Object instantiate(ClassLoader cls, String beanName,
+                                     BeanContext beanContext)
+            throws IOException, ClassNotFoundException {
         return Beans.instantiate(cls, beanName, beanContext, null);
     }
 
@@ -153,10 +155,18 @@
      *              object could not be found.
      * @exception IOException if an I/O error occurs.
      * @since 1.2
+     *
+     * @deprecated It is recommended to use
+     * {@link #instantiate(ClassLoader, String, BeanContext)},
+     * because the Applet API is deprecated. See the
+     * <a href="../../java/applet/package-summary.html"> java.applet package
+     * documentation</a> for further information.
      */
-    @SuppressWarnings("deprecation")
-    public static Object instantiate(ClassLoader cls, String beanName, BeanContext beanContext, AppletInitializer initializer)
-                        throws IOException, ClassNotFoundException {
+    @Deprecated(since = "9")
+    public static Object instantiate(ClassLoader cls, String beanName,
+                                     BeanContext beanContext,
+                                     AppletInitializer initializer)
+            throws IOException, ClassNotFoundException {
 
         InputStream ins;
         ObjectInputStream oins = null;
@@ -501,7 +511,7 @@
  * Package private support class.  This provides a default AppletContext
  * for beans which are applets.
  */
-@SuppressWarnings("deprecation")
+@Deprecated(since = "9")
 class BeansAppletContext implements AppletContext {
     Applet target;
     Hashtable<URL,Object> imageCache = new Hashtable<>();
@@ -586,7 +596,7 @@
  * Package private support class.  This provides an AppletStub
  * for beans which are applets.
  */
-@SuppressWarnings("deprecation")
+@Deprecated(since = "9")
 class BeansAppletStub implements AppletStub {
     transient boolean active;
     transient Applet target;
--- a/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java	Wed Jul 05 22:42:01 2017 +0200
@@ -260,6 +260,7 @@
      * Obtains the appropriate <code>Popup</code> based on
      * <code>popupType</code>.
      */
+    @SuppressWarnings("deprecation")
     private Popup getPopup(Component owner, Component contents,
                            int ownerX, int ownerY, int popupType) {
         if (GraphicsEnvironment.isHeadless()) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/RepaintManager.java	Wed Jul 05 22:42:01 2017 +0200
@@ -525,8 +525,12 @@
      * @param h Height of the region to repaint
      * @see JApplet#repaint
      * @since 1.6
+     *
+     * @deprecated The Applet API is deprecated. See the
+     * <a href="../../java/applet/package-summary.html"> java.applet package
+     * documentation</a> for further information.
      */
-    @SuppressWarnings("deprecation")
+    @Deprecated(since = "9")
     public void addDirtyRegion(Applet applet, int x, int y, int w, int h) {
         addDirtyRegion0(applet, x, y, w, h);
     }
--- a/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java	Wed Jul 05 22:42:01 2017 +0200
@@ -380,6 +380,12 @@
         // print the current section of the table
         g2d.translate(-clip.x, -clip.y);
         g2d.clip(clip);
+
+        // set a property so that BasicTableUI#paint can know JTable printMode
+        // is FIT_WIDTH since TablePrintable.printMode is not accessible from BasicTableUI
+        if (printMode == JTable.PrintMode.FIT_WIDTH) {
+            table.putClientProperty("Table.printMode", JTable.PrintMode.FIT_WIDTH);
+        }
         table.print(g2d);
 
         // restore the original transform and clip
@@ -407,8 +413,18 @@
         for(int visrow = rMin; visrow < rMax; visrow++) {
             rowHeight += table.getRowHeight(visrow);
         }
-        g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
+        // If PrintMode is FIT_WIDTH, then draw rect for entire column width while
+        // printing irrespective of how many columns are visible in console
+        if (printMode == JTable.PrintMode.FIT_WIDTH) {
+            g2d.drawRect(0, 0, clip.width, hclip.height + rowHeight);
+        } else {
+            g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
+        }
 
+        // clear the property
+        if (printMode == JTable.PrintMode.FIT_WIDTH) {
+            table.putClientProperty("Table.printMode", null);
+        }
         // dispose the graphics copy
         g2d.dispose();
 
@@ -534,5 +550,4 @@
         } while (clip.width + colWidth <= pw);
 
     }
-
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1812,12 +1812,12 @@
         }
 
         boolean ltr = table.getComponentOrientation().isLeftToRight();
-
+        Point upperLeft, lowerRight;
         // compute the visible part of table which needs to be painted
         Rectangle visibleBounds = clip.intersection(bounds);
-        Point upperLeft = visibleBounds.getLocation();
-        Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
-                                     visibleBounds.y + visibleBounds.height - 1);
+        upperLeft = visibleBounds.getLocation();
+        lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
+                               visibleBounds.y + visibleBounds.height - 1);
 
         int rMin = table.rowAtPoint(upperLeft);
         int rMax = table.rowAtPoint(lowerRight);
@@ -1834,6 +1834,18 @@
             rMax = table.getRowCount()-1;
         }
 
+        // For FIT_WIDTH, all columns should be printed irrespective of
+        // how many columns are visible. So, we used clip which is already set to
+        // total col width instead of visible region
+        // Since JTable.PrintMode is not accessible
+        // from here, we aet "Table.printMode" in TablePrintable#print and
+        // access from here.
+        Object printMode = table.getClientProperty("Table.printMode");
+        if ((printMode == JTable.PrintMode.FIT_WIDTH)) {
+            upperLeft = clip.getLocation();
+            lowerRight = new Point(clip.x + clip.width - 1,
+                                   clip.y + clip.height - 1);
+        }
         int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
         int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
         // This should never happen.
@@ -2018,7 +2030,7 @@
             int y = damagedArea.y;
             for (int row = rMin; row <= rMax; row++) {
                 y += table.getRowHeight(row);
-                g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
+                SwingUtilities2.drawHLine(g, damagedArea.x, tableWidth - 1, y - 1);
             }
         }
         if (table.getShowVerticalLines()) {
@@ -2030,14 +2042,14 @@
                 for (int column = cMin; column <= cMax; column++) {
                     int w = cm.getColumn(column).getWidth();
                     x += w;
-                    g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
+                    SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1);
                 }
             } else {
                 x = damagedArea.x;
                 for (int column = cMax; column >= cMin; column--) {
                     int w = cm.getColumn(column).getWidth();
                     x += w;
-                    g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
+                    SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1);
                 }
             }
         }
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java	Wed Jul 05 22:42:01 2017 +0200
@@ -27,10 +27,7 @@
 import sun.swing.SwingUtilities2;
 import java.awt.*;
 import java.awt.font.FontRenderContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import javax.swing.JPasswordField;
-import static javax.swing.text.PlainView.isFPMethodOverriden;
 
 /**
  * Implements a View suitable for use in JPasswordField
@@ -332,22 +329,6 @@
 
     static char[] ONE = new char[1];
 
-    private final boolean drawEchoCharacterOverridden;
-
-    {
-        final Class<?> CLS = getClass();
-        final Class<?> INT = Integer.TYPE;
-        final Class<?> FP = Float.TYPE;
-        final Class<?> CHAR = Character.TYPE;
-
-        drawEchoCharacterOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {Graphics.class, INT, INT, CHAR};
-                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, CHAR};
-                return isFPMethodOverriden("drawEchoCharacter", CLS, intTypes, fpTypes);
-            }
-        });
-    }
+    private final boolean drawEchoCharacterOverridden =
+            getFPMethodOverridden(getClass(), "drawEchoCharacter", FPMethodArgs.GNNC);
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Wed Jul 05 22:42:01 2017 +0200
@@ -32,6 +32,8 @@
 import java.util.Objects;
 import javax.swing.event.*;
 import java.lang.reflect.Module;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
 
 /**
  * Implements View interface for a simple multi-line text view
@@ -818,10 +820,45 @@
         return w;
     }
 
-    static boolean isFPMethodOverriden(String method,
-                                Class<?> cls,
-                                Class<?>[] intTypes,
-                                Class<?>[] fpTypes)
+    static boolean getFPMethodOverridden(Class<?> cls, String method,
+                                         FPMethodArgs methodArgs) {
+        HashMap<FPMethodItem, Boolean> map = null;
+        boolean initialized = methodsOverriddenMapRef != null
+                              && (map = methodsOverriddenMapRef.get()) != null;
+
+        if (!initialized) {
+            map = new HashMap<>();
+            methodsOverriddenMapRef = new SoftReference<>(map);
+        }
+
+        FPMethodItem key = new FPMethodItem(cls, method);
+        Boolean isFPMethodOverridden = map.get(key);
+        if (isFPMethodOverridden == null) {
+            isFPMethodOverridden = checkFPMethodOverridden(cls, method, methodArgs);
+            map.put(key, isFPMethodOverridden);
+        }
+        return isFPMethodOverridden;
+    }
+
+    private static boolean checkFPMethodOverridden(final Class<?> className,
+                                                   final String methodName,
+                                                   final FPMethodArgs methodArgs) {
+
+        return AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+                    @Override
+                    public Boolean run() {
+                        return isFPMethodOverridden(methodName, className,
+                                                    methodArgs.getMethodArguments(false),
+                                                    methodArgs.getMethodArguments(true));
+                    }
+                });
+    }
+
+    private static boolean isFPMethodOverridden(String method,
+                                                Class<?> cls,
+                                                Class<?>[] intTypes,
+                                                Class<?>[] fpTypes)
     {
         Module thisModule = PlainView.class.getModule();
         while (!thisModule.equals(cls.getModule())) {
@@ -840,6 +877,57 @@
         return true;
     }
 
+    enum FPMethodArgs {
+
+        IGNN,
+        IIGNN,
+        GNNII,
+        GNNC;
+
+        public Class<?>[] getMethodArguments(boolean isFPType) {
+            Class<?> N = (isFPType) ? Float.TYPE : Integer.TYPE;
+            Class<?> G = (isFPType) ? Graphics2D.class : Graphics.class;
+            switch (this) {
+                case IGNN:
+                    return new Class<?>[]{Integer.TYPE, G, N, N};
+                case IIGNN:
+                    return new Class<?>[]{Integer.TYPE, Integer.TYPE, G, N, N};
+                case GNNII:
+                    return new Class<?>[]{G, N, N, Integer.TYPE, Integer.TYPE};
+                case GNNC:
+                    return new Class<?>[]{G, N, N, Character.TYPE};
+                default:
+                    throw new RuntimeException("Unknown method arguments!");
+            }
+        }
+    }
+
+     private static class FPMethodItem {
+
+        final Class<?> className;
+        final String methodName;
+
+        public FPMethodItem(Class<?> className, String methodName) {
+            this.className = className;
+            this.methodName = methodName;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof FPMethodItem) {
+                FPMethodItem that = (FPMethodItem) obj;
+                return this.className.equals(that.className)
+                        && this.methodName.equals(that.methodName);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * methodName.hashCode() + className.hashCode();
+        }
+    }
+
     // --- member variables -----------------------------------------------
 
     /**
@@ -878,46 +966,13 @@
      */
     int firstLineOffset;
 
-    final boolean drawLineOverridden;
-    final boolean drawSelectedTextOverridden;
-    final boolean drawUnselectedTextOverridden;
-    final boolean useFloatingPointAPI;
-
-    {
-        final Class<?> CLS = getClass();
-        final Class<?> INT = Integer.TYPE;
-        final Class<?> FP = Float.TYPE;
-
-        drawLineOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {INT, Graphics.class, INT, INT};
-                Class<?>[] fpTypes = {INT, Graphics2D.class, FP, FP};
-                return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes);
-            }
-        });
-
-        drawUnselectedTextOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
-                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
-                return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes);
-            }
-        });
-
-        drawSelectedTextOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
-                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
-                return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes);
-            }
-        });
-
-        useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden;
-    }
+    private static SoftReference<HashMap<FPMethodItem, Boolean>> methodsOverriddenMapRef;
+    final boolean drawLineOverridden =
+            getFPMethodOverridden(getClass(), "drawLine", FPMethodArgs.IGNN);
+    final boolean drawSelectedTextOverridden =
+            getFPMethodOverridden(getClass(), "drawSelectedText", FPMethodArgs.GNNII);
+    final boolean drawUnselectedTextOverridden =
+            getFPMethodOverridden(getClass(), "drawUnselectedText", FPMethodArgs.GNNII);
+    final boolean useFloatingPointAPI =
+            drawUnselectedTextOverridden || drawSelectedTextOverridden;
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java	Wed Jul 05 22:42:01 2017 +0200
@@ -28,10 +28,9 @@
 import java.awt.font.FontRenderContext;
 import java.awt.geom.Rectangle2D;
 import java.lang.ref.SoftReference;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import javax.swing.event.*;
-import static javax.swing.text.PlainView.isFPMethodOverriden;
+import static javax.swing.text.PlainView.FPMethodArgs.*;
+import static javax.swing.text.PlainView.getFPMethodOverridden;
 
 /**
  * View of plain text (text with only one font and color)
@@ -989,46 +988,12 @@
         SoftReference<int[]> lineCache = null;
     }
 
-    private final boolean drawLineOverridden;
-    private final boolean drawSelectedTextOverridden;
-    private final boolean drawUnselectedTextOverridden;
-    private final boolean useFloatingPointAPI;
-
-    {
-        final Class<?> CLS = getClass();
-        final Class<?> INT = Integer.TYPE;
-        final Class<?> FP = Float.TYPE;
-
-        drawLineOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {INT, INT, Graphics.class, INT, INT};
-                Class<?>[] fpTypes = {INT, INT, Graphics2D.class, FP, FP};
-                return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes);
-            }
-        });
-
-        drawUnselectedTextOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
-                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
-                return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes);
-            }
-        });
-
-        drawSelectedTextOverridden = AccessController
-                .doPrivileged(new PrivilegedAction<Boolean>() {
-            @Override
-            public Boolean run() {
-                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
-                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
-                return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes);
-            }
-        });
-
-        useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden;
-    }
+    private final boolean drawLineOverridden =
+            getFPMethodOverridden(getClass(), "drawLine", IIGNN);
+    private final boolean drawSelectedTextOverridden =
+            getFPMethodOverridden(getClass(), "drawSelectedText", GNNII);
+    private final boolean drawUnselectedTextOverridden =
+            getFPMethodOverridden(getClass(), "drawUnselectedText", GNNII);
+    private final boolean useFloatingPointAPI =
+            drawUnselectedTextOverridden || drawSelectedTextOverridden;
 }
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletEvent.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletEvent.java	Wed Jul 05 22:42:01 2017 +0200
@@ -32,8 +32,13 @@
  * AppletEvent class.
  *
  * @author  Sunita Mani
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
 @SuppressWarnings("serial") // JDK-implementation class
+@Deprecated(since = "9")
 public class AppletEvent extends EventObject {
 
     private Object arg;
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletEventMulticaster.java	Wed Jul 05 22:42:01 2017 +0200
@@ -36,7 +36,12 @@
  * responsible for dispatching events to them.
  *
  * @author  Sunita Mani
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
+@Deprecated(since = "9")
 public class AppletEventMulticaster implements AppletListener {
 
     private final AppletListener a, b;
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletIOException.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletIOException.java	Wed Jul 05 22:42:01 2017 +0200
@@ -31,10 +31,14 @@
  * An applet IO exception.
  *
  * @author      Koji Uno
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
 @SuppressWarnings("serial") // JDK implementation class
-public
-class AppletIOException extends IOException {
+@Deprecated(since = "9")
+public class AppletIOException extends IOException {
     private String key = null;
     private Object msgobj = null;
 
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletIllegalArgumentException.java	Wed Jul 05 22:42:01 2017 +0200
@@ -29,10 +29,14 @@
  * An applet security exception.
  *
  * @author      Arthur van Hoff
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
 @SuppressWarnings("serial") // JDK implementation class
-public
-class AppletIllegalArgumentException extends IllegalArgumentException {
+@Deprecated(since = "9")
+public class AppletIllegalArgumentException extends IllegalArgumentException {
     private String key = null;
 
     public AppletIllegalArgumentException(String key) {
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletImageRef.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletImageRef.java	Wed Jul 05 22:42:01 2017 +0200
@@ -31,6 +31,7 @@
 import sun.awt.image.URLImageSource;
 import java.net.URL;
 
+@Deprecated(since = "9")
 class AppletImageRef {
     private SoftReference<Image> soft = null;
 
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletListener.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletListener.java	Wed Jul 05 22:42:01 2017 +0200
@@ -32,8 +32,12 @@
  * by objects interested in AppletEvents.
  *
  * @author  Sunita Mani
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
-
+@Deprecated(since = "9")
 public interface AppletListener extends EventListener {
     public void appletStateChanged(AppletEvent e);
 }
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletObjectInputStream.java	Wed Jul 05 22:42:01 2017 +0200
@@ -34,8 +34,12 @@
 /**
  * This subclass of ObjectInputStream delegates loading of classes to
  * an existing ClassLoader.
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
-
+@Deprecated(since = "9")
 class AppletObjectInputStream extends ObjectInputStream
 {
     private AppletClassLoader loader;
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java	Wed Jul 05 22:42:01 2017 +0200
@@ -52,9 +52,14 @@
  * thread group to call the applet's init(), start(), stop(), and
  * destroy() methods.
  *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
+ *
  * @author      Arthur van Hoff
  */
-@SuppressWarnings({"serial", "deprecation"}) // JDK implementation class
+@SuppressWarnings({"serial"}) // JDK implementation class
+@Deprecated(since = "9")
 public
 abstract class AppletPanel extends Panel implements AppletStub, Runnable {
 
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletProps.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletProps.java	Wed Jul 05 22:42:01 2017 +0200
@@ -36,6 +36,7 @@
 import sun.security.action.*;
 
 @SuppressWarnings("serial") // JDK implementation class
+@Deprecated(since = "9")
 class AppletProps extends Frame {
 
     TextField proxyHost;
@@ -197,6 +198,7 @@
 /* 4066432 */
 /* Dialog class to display property-related errors to user */
 @SuppressWarnings("serial") // JDK implementation class
+@Deprecated(since = "9")
 class AppletPropsErrorDialog extends Dialog {
     @SuppressWarnings("deprecation")
     public AppletPropsErrorDialog(Frame parent, String title, String message,
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java	Wed Jul 05 22:42:01 2017 +0200
@@ -43,6 +43,7 @@
  * A frame to show the applet tag in.
  */
 @SuppressWarnings("serial") // JDK-implementation class
+@Deprecated(since = "9")
 final class TextFrame extends Frame {
 
     /**
@@ -91,6 +92,7 @@
 /**
  * Lets us construct one using unix-style one shot behaviors.
  */
+@Deprecated(since = "9")
 final class StdAppletViewerFactory implements AppletViewerFactory {
 
     @Override
@@ -116,8 +118,13 @@
  * <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>.
  * (The document named appletviewertags.html in the JDK's docs/tooldocs directory,
  *  once the JDK docs have been installed.)
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
-@SuppressWarnings({"serial", "deprecation"}) // JDK-implementation class
+@SuppressWarnings({"serial"}) // JDK-implementation class
+@Deprecated(since = "9")
 public class AppletViewer extends Frame implements AppletContext, Printable {
 
     /**
@@ -146,7 +153,7 @@
      */
     AppletViewerFactory factory;
 
-
+    @Deprecated(since = "9")
     private final class UserActionListener implements ActionListener {
         @Override
         public void actionPerformed(ActionEvent evt) {
@@ -219,6 +226,7 @@
             }
         };
 
+        @Deprecated(since = "9")
         class AppletEventListener implements AppletListener
         {
             final Frame frame;
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerFactory.java	Wed Jul 05 22:42:01 2017 +0200
@@ -33,8 +33,8 @@
 import java.net.URL;
 import java.awt.MenuBar;
 
-public
-interface AppletViewerFactory {
+@Deprecated(since = "9")
+public interface AppletViewerFactory {
         public AppletViewer createAppletViewer(int x, int y, URL doc,
                                                Hashtable<String, String> atts);
         public MenuBar getBaseMenuBar();
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewerPanel.java	Wed Jul 05 22:42:01 2017 +0200
@@ -40,7 +40,12 @@
  * destroy() methods.
  *
  * @author      Arthur van Hoff
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
+@Deprecated(since = "9")
 class AppletViewerPanel extends AppletPanel {
 
     /* Are we debugging? */
--- a/jdk/src/java.desktop/share/classes/sun/applet/Main.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/applet/Main.java	Wed Jul 05 22:42:01 2017 +0200
@@ -39,7 +39,12 @@
 
 /**
  * The main entry point into AppletViewer.
+ *
+ * @deprecated The Applet API is deprecated. See the
+ * <a href="../../java/applet/package-summary.html"> java.applet package
+ * documentation</a> for further information.
  */
+@Deprecated(since = "9")
 public class Main {
     /**
      * The file which contains all of the AppletViewer specific properties.
--- a/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/awt/EmbeddedFrame.java	Wed Jul 05 22:42:01 2017 +0200
@@ -496,10 +496,14 @@
      * Checks if the component is in an EmbeddedFrame. If so,
      * returns the applet found in the hierarchy or null if
      * not found.
-     * @return the parent applet or {@ null}
+     * @return the parent applet or {@code null}
      * @since 1.6
+     *
+     * @deprecated The Applet API is deprecated. See the
+     * <a href="../../java/applet/package-summary.html"> java.applet package
+     * documentation</a> for further information.
      */
-    @SuppressWarnings("deprecation")
+    @Deprecated(since = "9")
     public static Applet getAppletIfAncestorOf(Component comp) {
         Container parent = comp.getParent();
         Applet applet = null;
--- a/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c	Wed Jul 05 22:42:01 2017 +0200
@@ -2419,7 +2419,7 @@
     case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:
         if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&
               SAFE_TO_ALLOC_2(width, 4) &&
-              SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 4)))
+              SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4)))
         {
             return -1;
         }
@@ -2428,7 +2428,7 @@
 
         if (offset < 0 || offset >= dataSize ||
             width > rasterP->scanlineStride ||
-            height * rasterP->scanlineStride * 4 > dataSize - offset)
+            ((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset)
         {
             // raster data buffer is too short
             return -1;
@@ -2446,7 +2446,7 @@
         return 0;
     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:
         if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&
-              SAFE_TO_ALLOC_2(height, rasterP->scanlineStride)))
+              SAFE_TO_ALLOC_2(rasterP->scanlineStride, height)))
         {
             return -1;
         }
@@ -2455,7 +2455,8 @@
 
         if (offset < 0 || offset >= dataSize ||
             width * rasterP->numBands > rasterP->scanlineStride ||
-            height * rasterP->scanlineStride > dataSize - offset)
+            ((width * rasterP->numBands) +
+             (height - 1) * rasterP->scanlineStride) > dataSize - offset)
         {
             // raster data buffer is too short
             return -1;
@@ -2474,7 +2475,7 @@
     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:
         if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&
               SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&
-              SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 2)))
+              SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 2)))
         {
               return -1;
         }
@@ -2483,7 +2484,8 @@
 
         if (offset < 0 || offset >= dataSize ||
             width * rasterP->numBands > rasterP->scanlineStride ||
-            height * rasterP->scanlineStride * 2 > dataSize - offset)
+            (((width * rasterP->numBands) +
+             (height - 1) * rasterP->scanlineStride)) * 2 > dataSize - offset)
         {
             // raster data buffer is too short
              return -1;
--- a/jdk/src/java.desktop/share/native/libmlib_image/safe_alloc.h	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/share/native/libmlib_image/safe_alloc.h	Wed Jul 05 22:42:01 2017 +0200
@@ -35,10 +35,10 @@
  */
 #define SAFE_TO_ALLOC_2(c, sz)                                             \
     (((c) > 0) && ((sz) > 0) &&                                            \
-     ((0xffffffffu / ((juint)(c))) > ((juint)(sz))))
+     ((0x7fffffff / (c)) > (sz)))
 
 #define SAFE_TO_ALLOC_3(w, h, sz)                                          \
     (((w) > 0) && ((h) > 0) && ((sz) > 0) &&                               \
-     (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz))))
+     (((0x7fffffff / (w)) / (h)) > (sz)))
 
 #endif // __SAFE_ALLOC_H__
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java	Wed Jul 05 22:42:01 2017 +0200
@@ -51,9 +51,9 @@
     boolean insets_corrected;
 
     XIconWindow iconWindow;
-    WindowDimensions dimensions;
+    volatile WindowDimensions dimensions;
     XContentWindow content;
-    Insets currentInsets;
+    volatile Insets currentInsets;
     XFocusProxyWindow focusProxy;
     static final Map<Class<?>,Insets> lastKnownInsets =
                                    Collections.synchronizedMap(new HashMap<>());
@@ -106,7 +106,7 @@
 
         // The lines that follow need to be in a postInit, so they
         // happen after the X window is created.
-        initResizability();
+        setResizable(winAttr.initialResizability);
         XWM.requestWMExtents(getWindow());
 
         content = XContentWindow.createContent(this);
@@ -130,7 +130,12 @@
 
     public void updateMinimumSize() {
         super.updateMinimumSize();
-        updateMinSizeHints();
+        XToolkit.awtLock();
+        try {
+            updateMinSizeHints();
+        } finally {
+            XToolkit.awtUnlock();
+        }
     }
 
     private void updateMinSizeHints() {
@@ -193,8 +198,13 @@
         if (log.isLoggable(PlatformLogger.Level.FINE)) {
             log.fine("Title is " + title);
         }
-        winAttr.title = title;
-        updateWMName();
+        XToolkit.awtLock();
+        try {
+            winAttr.title = title;
+            updateWMName();
+        } finally {
+            XToolkit.awtUnlock();
+        }
     }
 
     protected String getWMName() {
@@ -206,10 +216,10 @@
     }
 
     void updateWMName() {
-        super.updateWMName();
-        String name = getWMName();
         XToolkit.awtLock();
         try {
+            super.updateWMName();
+            String name = getWMName();
             if (name == null || name.trim().equals("")) {
                 name = "Java";
             }
@@ -304,6 +314,8 @@
         if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
             currentInsets = new Insets(0, 0, 0, 0);
             wm_set_insets = null;
+        } else {
+            insets_corrected = false;
         }
     }
 
@@ -330,7 +342,7 @@
             if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
                 getWMSetInsets(XAtom.get(ev.get_atom()));
             } else {
-                if(!isReparented()) {
+                if (!isReparented()) {
                     return;
                 }
                 wm_set_insets = null;
@@ -377,137 +389,127 @@
             insLog.fine(xe.toString());
         }
         reparent_serial = xe.get_serial();
-        XToolkit.awtLock();
-        try {
-            long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
+        long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
+
+        if (isEmbedded()) {
+            setReparented(true);
+            insets_corrected = true;
+            return;
+        }
+        if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
+            setReparented(true);
+            insets_corrected = true;
+            reshape(dimensions, SET_SIZE, false);
+        } else if (xe.get_parent() == root) {
+            configure_seen = false;
+            insets_corrected = false;
 
-            if (isEmbedded()) {
-                setReparented(true);
-                insets_corrected = true;
+            /*
+             * We can be repareted to root for two reasons:
+             *   . setVisible(false)
+             *   . WM exited
+             */
+            if (isVisible()) { /* WM exited */
+                /* Work around 4775545 */
+                XWM.getWM().unshadeKludge(this);
+                insLog.fine("- WM exited");
+            } else {
+                insLog.fine(" - reparent due to hide");
+            }
+        } else { /* reparented to WM frame, figure out our insets */
+            setReparented(true);
+            insets_corrected = false;
+            if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
                 return;
             }
-            Component t = target;
-            if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
-                setReparented(true);
-                insets_corrected = true;
-                reshape(dimensions, SET_SIZE, false);
-            } else if (xe.get_parent() == root) {
-                configure_seen = false;
-                insets_corrected = false;
 
-                /*
-                 * We can be repareted to root for two reasons:
-                 *   . setVisible(false)
-                 *   . WM exited
-                 */
-                if (isVisible()) { /* WM exited */
-                    /* Work around 4775545 */
-                    XWM.getWM().unshadeKludge(this);
-                    insLog.fine("- WM exited");
-                } else {
-                    insLog.fine(" - reparent due to hide");
+            // Check if we have insets provided by the WM
+            Insets correctWM = getWMSetInsets(null);
+            if (correctWM != null) {
+                if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
+                    insLog.finer("wm-provided insets {0}", correctWM);
                 }
-            } else { /* reparented to WM frame, figure out our insets */
-                setReparented(true);
-                insets_corrected = false;
-                if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
+                // If these insets are equal to our current insets - no actions are necessary
+                Insets dimInsets = dimensions.getInsets();
+                if (correctWM.equals(dimInsets)) {
+                    insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
+                    no_reparent_artifacts = true;
+                    insets_corrected = true;
+                    applyGuessedInsets();
                     return;
                 }
+            } else {
+                correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
+                if (correctWM != null) {
+                    correctWM = copyAndScaleDown(correctWM);
+                }
 
-                // Check if we have insets provided by the WM
-                Insets correctWM = getWMSetInsets(null);
-                if (correctWM != null) {
-                    if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
-                        insLog.finer("wm-provided insets {0}", correctWM);
-                    }
-                    // If these insets are equal to our current insets - no actions are necessary
-                    Insets dimInsets = dimensions.getInsets();
-                    if (correctWM.equals(dimInsets)) {
-                        insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
-                        no_reparent_artifacts = true;
-                        insets_corrected = true;
-                        applyGuessedInsets();
-                        return;
-                    }
-                } else {
-                    correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
+                if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
                     if (correctWM != null) {
-                        correctWM = copyAndScaleDown(correctWM);
-                    }
-
-                    if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
-                        if (correctWM != null) {
-                            insLog.finer("correctWM {0}", correctWM);
-                        } else {
-                            insLog.finer("correctWM insets are not available, waiting for configureNotify");
-                        }
+                        insLog.finer("correctWM {0}", correctWM);
+                    } else {
+                        insLog.finer("correctWM insets are not available, waiting for configureNotify");
                     }
                 }
+            }
 
-                if (correctWM != null) {
-                    handleCorrectInsets(correctWM);
-                }
+            if (correctWM != null) {
+                handleCorrectInsets(correctWM);
             }
-        } finally {
-            XToolkit.awtUnlock();
         }
     }
 
-    protected void handleCorrectInsets(Insets correctWM) {
-        XToolkit.awtLock();
-        try {
-            /*
-             * Ok, now see if we need adjust window size because
-             * initial insets were wrong (most likely they were).
-             */
-            Insets correction = difference(correctWM, currentInsets);
-            if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
-                insLog.finest("Corrention {0}", correction);
-            }
-            if (!isNull(correction)) {
-                currentInsets = copy(correctWM);
-                applyGuessedInsets();
+    private void handleCorrectInsets(Insets correctWM) {
+        /*
+         * Ok, now see if we need adjust window size because
+         * initial insets were wrong (most likely they were).
+         */
+        Insets correction = difference(correctWM, currentInsets);
+        if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
+            insLog.finest("Corrention {0}", correction);
+        }
+        if (!isNull(correction)) {
+            currentInsets = copy(correctWM);
+            applyGuessedInsets();
 
-                //Fix for 6318109: PIT: Min Size is not honored properly when a
-                //smaller size is specified in setSize(), XToolkit
-                //update minimum size hints
-                updateMinSizeHints();
-            }
-            if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
-                insLog.finer("Dimensions before reparent: " + dimensions);
-            }
-
-            dimensions.setInsets(getRealInsets());
-            insets_corrected = true;
+            //Fix for 6318109: PIT: Min Size is not honored properly when a
+            //smaller size is specified in setSize(), XToolkit
+            //update minimum size hints
+            updateMinSizeHints();
+        }
+        if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
+            insLog.finer("Dimensions before reparent: " + dimensions);
+        }
+        WindowDimensions newDimensions = new WindowDimensions(dimensions);
+        newDimensions.setInsets(getRealInsets());
+        dimensions = newDimensions;
+        insets_corrected = true;
 
-            if (isMaximized()) {
-                return;
-            }
+        if (isMaximized()) {
+            return;
+        }
 
-            /*
-             * If this window has been sized by a pack() we need
-             * to keep the interior geometry intact.  Since pack()
-             * computed width and height with wrong insets, we
-             * must adjust the target dimensions appropriately.
-             */
-            if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
-                reshape(dimensions, SET_BOUNDS, false);
-            } else {
-                reshape(dimensions, SET_SIZE, false);
-            }
-        } finally {
-            XToolkit.awtUnlock();
+        /*
+         * If this window has been sized by a pack() we need
+         * to keep the interior geometry intact.  Since pack()
+         * computed width and height with wrong insets, we
+         * must adjust the target dimensions appropriately.
+         */
+        if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
+            reshape(dimensions, SET_BOUNDS, false);
+        } else {
+            reshape(dimensions, SET_SIZE, false);
         }
     }
 
-    public void handleMoved(WindowDimensions dims) {
+    void handleMoved(WindowDimensions dims) {
         Point loc = dims.getLocation();
         AWTAccessor.getComponentAccessor().setLocation(target, loc.x, loc.y);
         postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
     }
 
 
-    protected Insets guessInsets() {
+    private Insets guessInsets() {
         if (isEmbedded() || isTargetUndecorated()) {
             return new Insets(0, 0, 0, 0);
         } else {
@@ -532,16 +534,7 @@
         currentInsets = copy(guessed);
     }
 
-    public void revalidate() {
-        XToolkit.executeOnEventHandlerThread(target, new Runnable() {
-                public void run() {
-                    target.invalidate();
-                    target.validate();
-                }
-            });
-    }
-
-    Insets getRealInsets() {
+    private Insets getRealInsets() {
         if (isNull(currentInsets)) {
             applyGuessedInsets();
         }
@@ -578,7 +571,7 @@
 
     // Coordinates are that of the target
     // Called only on Toolkit thread
-    public void reshape(WindowDimensions newDimensions, int op,
+    private void reshape(WindowDimensions newDimensions, int op,
                         boolean userReshape)
     {
         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
@@ -599,81 +592,75 @@
             }
             newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet());
         }
-        XToolkit.awtLock();
-        try {
-            if (!isReparented() || !isVisible()) {
-                if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
-                    insLog.fine("- not reparented({0}) or not visible({1}), default reshape",
-                           Boolean.valueOf(isReparented()), Boolean.valueOf(visible));
-                }
-
-                // Fix for 6323293.
-                // This actually is needed to preserve compatibility with previous releases -
-                // some of licensees are expecting componentMoved event on invisible one while
-                // its location changes.
-                Point oldLocation = getLocation();
+        if (!isReparented() || !isVisible()) {
+            if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
+                insLog.fine("- not reparented({0}) or not visible({1}), default reshape",
+                       Boolean.valueOf(isReparented()), Boolean.valueOf(visible));
+            }
 
-                Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX(target),
-                                              AWTAccessor.getComponentAccessor().getY(target));
-
-                if (!newLocation.equals(oldLocation)) {
-                    handleMoved(newDimensions);
-                }
+            // Fix for 6323293.
+            // This actually is needed to preserve compatibility with previous releases -
+            // some of licensees are expecting componentMoved event on invisible one while
+            // its location changes.
+            Point oldLocation = getLocation();
 
-                dimensions = new WindowDimensions(newDimensions);
-                updateSizeHints(dimensions);
-                Rectangle client = dimensions.getClientRect();
-                checkShellRect(client);
-                setShellBounds(client);
-                if (content != null &&
-                    !content.getSize().equals(newDimensions.getSize()))
-                {
-                    reconfigureContentWindow(newDimensions);
-                }
-                return;
+            Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX(target),
+                                          AWTAccessor.getComponentAccessor().getY(target));
+
+            if (!newLocation.equals(oldLocation)) {
+                handleMoved(newDimensions);
             }
 
-            int wm = XWM.getWMID();
-            updateChildrenSizes();
-            applyGuessedInsets();
-
-            Rectangle shellRect = newDimensions.getClientRect();
-
-            if (gravityBug()) {
-                Insets in = newDimensions.getInsets();
-                shellRect.translate(in.left, in.top);
+            dimensions = new WindowDimensions(newDimensions);
+            updateSizeHints(dimensions);
+            Rectangle client = dimensions.getClientRect();
+            checkShellRect(client);
+            setShellBounds(client);
+            if (content != null &&
+                !content.getSize().equals(newDimensions.getSize()))
+            {
+                reconfigureContentWindow(newDimensions);
             }
+            return;
+        }
 
-            if ((op & NO_EMBEDDED_CHECK) == 0 && isEmbedded()) {
-                shellRect.setLocation(0, 0);
-            }
+        updateChildrenSizes();
+        applyGuessedInsets();
 
-            checkShellRectSize(shellRect);
-            if (!isEmbedded()) {
-                checkShellRectPos(shellRect);
-            }
+        Rectangle shellRect = newDimensions.getClientRect();
+
+        if (gravityBug()) {
+            Insets in = newDimensions.getInsets();
+            shellRect.translate(in.left, in.top);
+        }
 
-            op = op & ~NO_EMBEDDED_CHECK;
+        if ((op & NO_EMBEDDED_CHECK) == 0 && isEmbedded()) {
+            shellRect.setLocation(0, 0);
+        }
 
-            if (op == SET_LOCATION) {
-                setShellPosition(shellRect);
-            } else if (isResizable()) {
-                if (op == SET_BOUNDS) {
-                    setShellBounds(shellRect);
-                } else {
-                    setShellSize(shellRect);
-                }
+        checkShellRectSize(shellRect);
+        if (!isEmbedded()) {
+            checkShellRectPos(shellRect);
+        }
+
+        op = op & ~NO_EMBEDDED_CHECK;
+
+        if (op == SET_LOCATION) {
+            setShellPosition(shellRect);
+        } else if (isResizable()) {
+            if (op == SET_BOUNDS) {
+                setShellBounds(shellRect);
             } else {
-                XWM.setShellNotResizable(this, newDimensions, shellRect, true);
-                if (op == SET_BOUNDS) {
-                    setShellPosition(shellRect);
-                }
+                setShellSize(shellRect);
             }
+        } else {
+            XWM.setShellNotResizable(this, newDimensions, shellRect, true);
+            if (op == SET_BOUNDS) {
+                setShellPosition(shellRect);
+            }
+        }
 
-            reconfigureContentWindow(newDimensions);
-        } finally {
-            XToolkit.awtUnlock();
-        }
+        reconfigureContentWindow(newDimensions);
     }
 
     /**
@@ -682,8 +669,6 @@
     private void reshape(int x, int y, int width, int height, int operation,
                          boolean userReshape)
     {
-        Rectangle newRec;
-        boolean setClient = false;
         WindowDimensions dims = new WindowDimensions(dimensions);
         switch (operation & (~NO_EMBEDDED_CHECK)) {
           case SET_LOCATION:
@@ -726,7 +711,12 @@
      */
     public void setBounds(int x, int y, int width, int height, int op) {
         // TODO: Rewrite with WindowDimensions
-        reshape(x, y, width, height, op, true);
+        XToolkit.awtLock();
+        try {
+            reshape(x, y, width, height, op, true);
+        } finally {
+            XToolkit.awtUnlock();
+        }
         validateSurface();
     }
 
@@ -861,81 +851,74 @@
         checkShellRectPos(shellRect);
     }
 
-    public void setShellBounds(Rectangle rec) {
+    private void setShellBounds(Rectangle rec) {
         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
             insLog.fine("Setting shell bounds on " + this + " to " + rec);
         }
-        XToolkit.awtLock();
-        try {
-            updateSizeHints(rec.x, rec.y, rec.width, rec.height);
-            XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getShell(),
-                                          scaleUp(rec.x), scaleUp(rec.y),
-                                          scaleUp(rec.width), scaleUp(rec.height));
-        }
-        finally {
-            XToolkit.awtUnlock();
-        }
+        updateSizeHints(rec.x, rec.y, rec.width, rec.height);
+        XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getShell(),
+                                      scaleUp(rec.x), scaleUp(rec.y),
+                                      scaleUp(rec.width), scaleUp(rec.height));
     }
-    public void setShellSize(Rectangle rec) {
+
+    private void setShellSize(Rectangle rec) {
         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
             insLog.fine("Setting shell size on " + this + " to " + rec);
         }
-        XToolkit.awtLock();
-        try {
-            updateSizeHints(rec.x, rec.y, rec.width, rec.height);
-            XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(),
-                                      scaleUp(rec.width), scaleUp(rec.height));
-        }
-        finally {
-            XToolkit.awtUnlock();
-        }
+        updateSizeHints(rec.x, rec.y, rec.width, rec.height);
+        XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(),
+                                  scaleUp(rec.width), scaleUp(rec.height));
     }
-    public void setShellPosition(Rectangle rec) {
+
+    private void setShellPosition(Rectangle rec) {
         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
             insLog.fine("Setting shell position on " + this + " to " + rec);
         }
-        XToolkit.awtLock();
-        try {
-            updateSizeHints(rec.x, rec.y, rec.width, rec.height);
-            XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(),
-                                    scaleUp(rec.x), scaleUp(rec.y));
-        }
-        finally {
-            XToolkit.awtUnlock();
-        }
+        updateSizeHints(rec.x, rec.y, rec.width, rec.height);
+        XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(),
+                                scaleUp(rec.x), scaleUp(rec.y));
     }
 
-    void initResizability() {
-        setResizable(winAttr.initialResizability);
-    }
     public void setResizable(boolean resizable) {
-        int fs = winAttr.functions;
-        if (!isResizable() && resizable) {
-            resetWMSetInsets();
-            if (!isEmbedded()) {
-                setReparented(false);
-            }
-            winAttr.isResizable = resizable;
-            if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
-                fs &= ~(MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
-            } else {
-                fs |= (MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
+        XToolkit.awtLock();
+        try {
+            int fs = winAttr.functions;
+            if (!isResizable() && resizable) {
+                resetWMSetInsets();
+                if (!isEmbedded()) {
+                    setReparented(false);
+                }
+                winAttr.isResizable = resizable;
+                if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
+                    fs &= ~(MWMConstants.MWM_FUNC_RESIZE
+                          | MWMConstants.MWM_FUNC_MAXIMIZE);
+                } else {
+                    fs |= (MWMConstants.MWM_FUNC_RESIZE
+                         | MWMConstants.MWM_FUNC_MAXIMIZE);
+                }
+                winAttr.functions = fs;
+                XWM.setShellResizable(this);
+            } else if (isResizable() && !resizable) {
+                resetWMSetInsets();
+                if (!isEmbedded()) {
+                    setReparented(false);
+                }
+                winAttr.isResizable = resizable;
+                if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
+                    fs |= (MWMConstants.MWM_FUNC_RESIZE
+                         | MWMConstants.MWM_FUNC_MAXIMIZE);
+                } else {
+                    fs &= ~(MWMConstants.MWM_FUNC_RESIZE
+                          | MWMConstants.MWM_FUNC_MAXIMIZE);
+                }
+                winAttr.functions = fs;
+                XWM.setShellNotResizable(this, dimensions,
+                        XWM.getWMID() == XWM.UNITY_COMPIZ_WM && configure_seen ?
+                        dimensions.getScreenBounds() :
+                        dimensions.getBounds(), false);
             }
-            winAttr.functions = fs;
-            XWM.setShellResizable(this);
-        } else if (isResizable() && !resizable) {
-            resetWMSetInsets();
-            if (!isEmbedded()) {
-                setReparented(false);
-            }
-            winAttr.isResizable = resizable;
-            if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
-                fs |= (MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
-            } else {
-                fs &= ~(MWMConstants.MWM_FUNC_RESIZE | MWMConstants.MWM_FUNC_MAXIMIZE);
-            }
-            winAttr.functions = fs;
-            XWM.setShellNotResizable(this, dimensions, dimensions.getBounds(), false);
+        } finally {
+            XToolkit.awtUnlock();
         }
     }
 
@@ -990,17 +973,16 @@
         try {
             if (configure_seen) {
                 return toGlobal(0,0);
-            } else {
-                Point location = target.getLocation();
-                if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
-                    insLog.fine("getLocationOnScreen {0} not reparented: {1} ",
-                                this, location);
-                }
-                return location;
             }
         } finally {
             XToolkit.awtUnlock();
         }
+        Point location = target.getLocation();
+        if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
+            insLog.fine("getLocationOnScreen {0} not reparented: {1} ",
+                        this, location);
+        }
+        return location;
     }
 
 
@@ -1134,7 +1116,7 @@
         return focusProxy;
     }
 
-    public void handleQuit() {
+    private void handleQuit() {
         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
     }
 
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1029,8 +1029,14 @@
         }
         XToolkit.awtLock();
         try {
-            Rectangle shellBounds = window.getShellBounds();
-            shellBounds.translate(-window.currentInsets.left, -window.currentInsets.top);
+            Rectangle shellBounds;
+            if (getWMID() != UNITY_COMPIZ_WM) {
+                shellBounds = window.getShellBounds();
+                shellBounds.translate(-window.currentInsets.left,
+                                      -window.currentInsets.top);
+            } else {
+                shellBounds = window.getDimensions().getScreenBounds();
+            }
             window.updateSizeHints(window.getDimensions());
             requestWMExtents(window.getWindow());
             XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(),
--- a/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1053,15 +1053,8 @@
             // of setting it, it is a safe assumption to just always
             // include SheetCollate as supported attribute.
 
-            /*
-               In Linux, we use Postscript for rendering but Linux still
-               has issues in propagating Postscript-embedded setpagedevice
-               setting like collation.  Therefore, we temporarily exclude
-               Linux.
-            */
-            if (!PrintServiceLookupProvider.isLinux()) {
-                catList.add(SheetCollate.class);
-            }
+            catList.add(SheetCollate.class);
+
         }
 
         // With the assumption that  Chromaticity is equivalent to
--- a/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -362,59 +362,81 @@
     }
 
     /**
-     * Main program to start a registry. <br>
-     * The port number can be specified on the command line.
+     * Return a new RegistryImpl on the requested port and export it to serve
+     * registry requests. A classloader is initialized from the system property
+     * "env.class.path" and a security manager is set unless one is already set.
+     * <p>
+     * The returned Registry is fully functional within the current process and
+     * is usable for internal and testing purposes.
+     *
+     * @param regPort port on which the rmiregistry accepts requests;
+     *                if 0, an implementation specific port is assigned
+     * @return a RegistryImpl instance
+     * @exception RemoteException If remote operation failed.
+     * @since 9
      */
-    public static void main(String args[])
-    {
+    public static RegistryImpl createRegistry(int regPort) throws RemoteException {
         // Create and install the security manager if one is not installed
         // already.
         if (System.getSecurityManager() == null) {
             System.setSecurityManager(new SecurityManager());
         }
 
+        /*
+         * Fix bugid 4147561: When JDK tools are executed, the value of
+         * the CLASSPATH environment variable for the shell in which they
+         * were invoked is no longer incorporated into the application
+         * class path; CLASSPATH's only effect is to be the value of the
+         * system property "env.class.path".  To preserve the previous
+         * (JDK1.1 and JDK1.2beta3) behavior of this tool, however, its
+         * CLASSPATH should still be considered when resolving classes
+         * being unmarshalled.  To effect this old behavior, a class
+         * loader that loads from the file path specified in the
+         * "env.class.path" property is created and set to be the context
+         * class loader before the remote object is exported.
+         */
+        String envcp = System.getProperty("env.class.path");
+        if (envcp == null) {
+            envcp = ".";            // preserve old default behavior
+        }
+        URL[] urls = pathToURLs(envcp);
+        ClassLoader cl = new URLClassLoader(urls);
+
+        /*
+         * Fix bugid 4242317: Classes defined by this class loader should
+         * be annotated with the value of the "java.rmi.server.codebase"
+         * property, not the "file:" URLs for the CLASSPATH elements.
+         */
+        sun.rmi.server.LoaderHandler.registerCodebaseLoader(cl);
+
+        Thread.currentThread().setContextClassLoader(cl);
+
+        RegistryImpl registryImpl = null;
         try {
-            /*
-             * Fix bugid 4147561: When JDK tools are executed, the value of
-             * the CLASSPATH environment variable for the shell in which they
-             * were invoked is no longer incorporated into the application
-             * class path; CLASSPATH's only effect is to be the value of the
-             * system property "env.class.path".  To preserve the previous
-             * (JDK1.1 and JDK1.2beta3) behavior of this tool, however, its
-             * CLASSPATH should still be considered when resolving classes
-             * being unmarshalled.  To effect this old behavior, a class
-             * loader that loads from the file path specified in the
-             * "env.class.path" property is created and set to be the context
-             * class loader before the remote object is exported.
-             */
-            String envcp = System.getProperty("env.class.path");
-            if (envcp == null) {
-                envcp = ".";            // preserve old default behavior
-            }
-            URL[] urls = pathToURLs(envcp);
-            ClassLoader cl = new URLClassLoader(urls);
+            registryImpl = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<RegistryImpl>() {
+                    public RegistryImpl run() throws RemoteException {
+                        return new RegistryImpl(regPort);
+                    }
+                }, getAccessControlContext(regPort));
+        } catch (PrivilegedActionException ex) {
+            throw (RemoteException) ex.getException();
+        }
 
-            /*
-             * Fix bugid 4242317: Classes defined by this class loader should
-             * be annotated with the value of the "java.rmi.server.codebase"
-             * property, not the "file:" URLs for the CLASSPATH elements.
-             */
-            sun.rmi.server.LoaderHandler.registerCodebaseLoader(cl);
+        return registryImpl;
+    }
 
-            Thread.currentThread().setContextClassLoader(cl);
-
+    /**
+     * Main program to start a registry. <br>
+     * The port number can be specified on the command line.
+     */
+    public static void main(String args[])
+    {
+        try {
             final int regPort = (args.length >= 1) ? Integer.parseInt(args[0])
                                                    : Registry.REGISTRY_PORT;
-            try {
-                registry = AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<RegistryImpl>() {
-                        public RegistryImpl run() throws RemoteException {
-                            return new RegistryImpl(regPort);
-                        }
-                    }, getAccessControlContext(regPort));
-            } catch (PrivilegedActionException ex) {
-                throw (RemoteException) ex.getException();
-            }
+
+            registry = createRegistry(regPort);
 
             // prevent registry from exiting
             while (true) {
--- a/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp	Wed Jul 05 22:42:01 2017 +0200
@@ -102,26 +102,26 @@
 
 JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalWidth
   (JNIEnv *, jobject) {
-    HANDLE hStdIn;
-    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+    HANDLE hStdOut;
+    if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
         return -1;
     }
     CONSOLE_SCREEN_BUFFER_INFO info;
-    if (! GetConsoleScreenBufferInfo(hStdIn, &info)) {
+    if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
         return -1;
     }
-    return info.dwSize.X;
+    return info.srWindow.Right - info.srWindow.Left;
 }
 
 JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalHeight
   (JNIEnv *, jobject) {
-    HANDLE hStdIn;
-    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
+    HANDLE hStdOut;
+    if ((hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
         return -1;
     }
     CONSOLE_SCREEN_BUFFER_INFO info;
-    if (! GetConsoleScreenBufferInfo(hStdIn, &info)) {
+    if (! GetConsoleScreenBufferInfo(hStdOut, &info)) {
         return -1;
     }
-    return info.dwSize.Y;
+    return info.srWindow.Bottom - info.srWindow.Top + 1;
 }
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,8 @@
 import java.nio.file.Paths;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+
+import jdk.internal.module.ModulePath;
 import jdk.internal.module.ModuleResolution;
 
 /**
@@ -155,8 +157,8 @@
                     for (String dir : dirs) {
                         paths[i++] = Paths.get(dir);
                     }
-                    jartool.moduleFinder = ModuleFinder.compose(jartool.moduleFinder,
-                                                                ModuleFinder.of(paths));
+                    jartool.moduleFinder =
+                        new ModulePath(Runtime.version(), true, paths);
                 }
             },
             new Option(false, OptionType.CREATE_UPDATE, "--do-not-resolve-by-default") {
@@ -169,9 +171,9 @@
             new Option(true, OptionType.CREATE_UPDATE, "--warn-if-resolved") {
                 void process(Main jartool, String opt, String arg) throws BadArgs {
                     ModuleResolution mres = ModuleResolution.empty();
-                    if (jartool.moduleResolution.doNotResolveByDefault())
+                    if (jartool.moduleResolution.doNotResolveByDefault()) {
                         mres.withDoNotResolveByDefault();
-
+                    }
                     if (arg.equals("deprecated")) {
                         jartool.moduleResolution = mres.withDeprecated();
                     } else if (arg.equals("deprecated-for-removal")) {
@@ -201,26 +203,27 @@
             // Other options
             new Option(true, true, OptionType.OTHER, "--help", "-h") {
                 void process(Main jartool, String opt, String arg) throws BadArgs {
-                    if (arg == null) {
-                        jartool.info = Main.Info.HELP;
-                        return;
+                    if (jartool.info == null) {
+                        if (arg == null) {
+                            jartool.info = GNUStyleOptions::printHelp;  //  Main.Info.HELP;
+                            return;
+                        }
+                        if (!arg.equals("compat"))
+                            throw new BadArgs("error.illegal.option", arg).showUsage(true);
+                        // jartool.info = Main.Info.COMPAT_HELP;
+                        jartool.info = GNUStyleOptions::printCompatHelp;
                     }
-
-                    if (!arg.equals("compat"))
-                        throw new BadArgs("error.illegal.option", arg).showUsage(true);
-
-                    jartool.info = Main.Info.COMPAT_HELP;
                 }
             },
             new Option(false, OptionType.OTHER, "--help-extra") {
                 void process(Main jartool, String opt, String arg) throws BadArgs {
-                    jartool.info = Main.Info.HELP_EXTRA;
+                    jartool.info = GNUStyleOptions::printHelpExtra;
                 }
             },
             new Option(false, OptionType.OTHER, "--version") {
                 void process(Main jartool, String opt, String arg) {
                     if (jartool.info == null)
-                        jartool.info = Main.Info.VERSION;
+                        jartool.info = GNUStyleOptions::printVersion;
                 }
             }
     };
@@ -279,14 +282,14 @@
     static int parseOptions(Main jartool, String[] args) throws BadArgs {
         int count = 0;
         if (args.length == 0) {
-            jartool.info = Main.Info.USAGE_TRYHELP;
+            jartool.info = GNUStyleOptions::printUsageTryHelp;  //  never be here
             return 0;
         }
 
         // process options
         for (; count < args.length; count++) {
-            if (args[count].charAt(0) != '-' || args[count].equals("-C")
-                || args[count].equals("--release"))
+            if (args[count].charAt(0) != '-' || args[count].equals("-C") ||
+                args[count].equals("--release"))
                 break;
 
             String name = args[count];
@@ -322,15 +325,15 @@
         throw new BadArgs("error.unrecognized.option", name).showUsage(true);
     }
 
-    static void printHelp(PrintWriter out) {
-        printHelp(out, false);
+    static void printHelpExtra(PrintWriter out) {
+        printHelp0(out, true);
     }
 
-    static void printHelpExtra(PrintWriter out) {
-        printHelp(out, true);
+    static void printHelp(PrintWriter out) {
+        printHelp0(out, false);
     }
 
-    private static void printHelp(PrintWriter out, boolean printExtra) {
+    private static void printHelp0(PrintWriter out, boolean printExtra) {
         out.format("%s%n", Main.getMsg("main.help.preopt"));
         for (OptionType type : OptionType.values()) {
             boolean typeHeadingWritten = false;
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 
 import java.io.*;
 import java.lang.module.Configuration;
+import java.lang.module.InvalidModuleDescriptorException;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
 import java.lang.module.ModuleDescriptor.Provides;
@@ -46,7 +47,7 @@
 import java.nio.file.StandardCopyOption;
 import java.util.*;
 import java.util.function.Consumer;
-import java.util.function.Function;
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -58,6 +59,7 @@
 
 import jdk.internal.module.Checks;
 import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleHashesBuilder;
 import jdk.internal.module.ModuleInfo;
 import jdk.internal.module.ModuleInfoExtender;
 import jdk.internal.module.ModuleResolution;
@@ -66,7 +68,6 @@
 import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
 import static java.util.jar.JarFile.MANIFEST_NAME;
 import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toSet;
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 
 /**
@@ -74,58 +75,24 @@
  * (Java Archive) file format. The JAR format is based on the ZIP file
  * format, with optional meta-information stored in a MANIFEST entry.
  */
-public
-class Main {
+public class Main {
     String program;
     PrintWriter out, err;
     String fname, mname, ename;
     String zname = "";
     String rootjar = null;
-    Set<String> concealedPackages = new HashSet<>(); // used by Validator
 
     private static final int BASE_VERSION = 0;
 
-    class Entry {
-        final String basename;
-        final String entryname;
+    private static class Entry {
+        final String name;
         final File file;
         final boolean isDir;
 
-        Entry(File file, String basename, String entryname) {
-            this.file = file;
-            this.isDir = file.isDirectory();
-            this.basename = basename;
-            this.entryname = entryname;
-        }
-
-        Entry(int version, File file) {
+        Entry(File file, String name, boolean isDir) {
             this.file = file;
-            String path = file.getPath();
-            if (file.isDirectory()) {
-                isDir = true;
-                path = path.endsWith(File.separator) ? path :
-                            path + File.separator;
-            } else {
-                isDir = false;
-            }
-            EntryName en = new EntryName(path, version);
-            basename = en.baseName;
-            entryname = en.entryName;
-        }
-
-        /**
-         * Returns a new Entry that trims the versions directory.
-         *
-         * This entry should be a valid entry matching the given version.
-         */
-        Entry toVersionedEntry(int version) {
-            assert isValidVersionedEntry(this, version);
-
-            if (version == BASE_VERSION)
-                return this;
-
-            EntryName en = new EntryName(trimVersionsDir(basename, version), version);
-            return new Entry(this.file, en.baseName, en.entryName);
+            this.isDir = isDir;
+            this.name = name;
         }
 
         @Override
@@ -141,32 +108,6 @@
         }
     }
 
-    class EntryName {
-        final String baseName;
-        final String entryName;
-
-        EntryName(String name, int version) {
-            name = name.replace(File.separatorChar, '/');
-            String matchPath = "";
-            for (String path : pathsMap.get(version)) {
-                if (name.startsWith(path)
-                        && (path.length() > matchPath.length())) {
-                    matchPath = path;
-                }
-            }
-            name = safeName(name.substring(matchPath.length()));
-            // the old implementaton doesn't remove
-            // "./" if it was led by "/" (?)
-            if (name.startsWith("./")) {
-                name = name.substring(2);
-            }
-            baseName = name;
-            entryName = (version > BASE_VERSION)
-                    ? VERSIONS_DIR + version + "/" + baseName
-                    : baseName;
-        }
-    }
-
     // An entryName(path)->Entry map generated during "expand", it helps to
     // decide whether or not an existing entry in a jar file needs to be
     // replaced, during the "update" operation.
@@ -175,11 +116,8 @@
     // All entries need to be added/updated.
     Set<Entry> entries = new LinkedHashSet<>();
 
-    // All packages.
-    Set<String> packages = new HashSet<>();
-    // All actual entries added, or existing, in the jar file ( excl manifest
-    // and module-info.class ). Populated during create or update.
-    Set<String> jarEntries = new HashSet<>();
+    // module-info.class entries need to be added/updated.
+    Map<String,byte[]> moduleInfos = new HashMap<>();
 
     // A paths Set for each version, where each Set contains directories
     // specified by the "-C" operation.
@@ -208,19 +146,7 @@
     boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag;
 
     /* To support additional GNU Style informational options */
-    enum Info {
-        HELP(GNUStyleOptions::printHelp),
-        HELP_EXTRA(GNUStyleOptions::printHelpExtra),
-        COMPAT_HELP(GNUStyleOptions::printCompatHelp),
-        USAGE_TRYHELP(GNUStyleOptions::printUsageTryHelp),
-        VERSION(GNUStyleOptions::printVersion);
-
-        private Consumer<PrintWriter> printFunction;
-        Info(Consumer<PrintWriter> f) { this.printFunction = f; }
-        void print(PrintWriter out) { printFunction.accept(out); }
-    };
-    Info info;
-
+    Consumer<PrintWriter> info;
 
     /* Modular jar related options */
     Version moduleVersion;
@@ -228,8 +154,7 @@
     ModuleResolution moduleResolution = ModuleResolution.empty();
     ModuleFinder moduleFinder = ModuleFinder.of();
 
-    private static final String MODULE_INFO = "module-info.class";
-
+    static final String MODULE_INFO = "module-info.class";
     static final String MANIFEST_DIR = "META-INF/";
     static final String VERSIONS_DIR = MANIFEST_DIR + "versions/";
     static final String VERSION = "1.0";
@@ -324,7 +249,6 @@
                     }
                 }
             }
-
             if (cflag) {
                 Manifest manifest = null;
                 if (!Mflag) {
@@ -347,72 +271,60 @@
                         addMultiRelease(manifest);
                     }
                 }
-
-                Map<String,Path> moduleInfoPaths = new HashMap<>();
-                for (int version : filesMap.keySet()) {
-                    String[] files = filesMap.get(version);
-                    expand(null, files, false, moduleInfoPaths, version);
-                }
-
-                Map<String,byte[]> moduleInfos = new LinkedHashMap<>();
-                if (!moduleInfoPaths.isEmpty()) {
-                    if (!checkModuleInfos(moduleInfoPaths))
-                        return false;
-
-                    // root module-info first
-                    byte[] b = readModuleInfo(moduleInfoPaths.get(MODULE_INFO));
-                    moduleInfos.put(MODULE_INFO, b);
-                    for (Map.Entry<String,Path> e : moduleInfoPaths.entrySet())
-                        moduleInfos.putIfAbsent(e.getKey(), readModuleInfo(e.getValue()));
-
-                    if (!addExtendedModuleAttributes(moduleInfos))
-                        return false;
+                expand();
+                if (!moduleInfos.isEmpty()) {
+                    // All actual file entries (excl manifest and module-info.class)
+                    Set<String> jentries = new HashSet<>();
+                    // all packages if it's a class or resource
+                    Set<String> packages = new HashSet<>();
+                    entries.stream()
+                           .filter(e -> !e.isDir)
+                           .forEach( e -> {
+                               addPackageIfNamed(packages, e.name);
+                               jentries.add(e.name);
+                    });
+                    addExtendedModuleAttributes(moduleInfos, packages);
 
                     // Basic consistency checks for modular jars.
-                    if (!checkServices(moduleInfos.get(MODULE_INFO)))
+                    if (!checkModuleInfo(moduleInfos.get(MODULE_INFO), jentries))
                         return false;
 
                 } else if (moduleVersion != null || modulesToHash != null) {
                     error(getMsg("error.module.options.without.info"));
                     return false;
                 }
-
                 if (vflag && fname == null) {
                     // Disable verbose output so that it does not appear
                     // on stdout along with file data
                     // error("Warning: -v option ignored");
                     vflag = false;
                 }
-
                 final String tmpbase = (fname == null)
                         ? "tmpjar"
                         : fname.substring(fname.indexOf(File.separatorChar) + 1);
+
                 File tmpfile = createTemporaryFile(tmpbase, ".jar");
-
                 try (OutputStream out = new FileOutputStream(tmpfile)) {
-                    create(new BufferedOutputStream(out, 4096), manifest, moduleInfos);
+                    create(new BufferedOutputStream(out, 4096), manifest);
                 }
-
                 if (nflag) {
                     File packFile = createTemporaryFile(tmpbase, ".pack");
                     try {
                         Packer packer = Pack200.newPacker();
                         Map<String, String> p = packer.properties();
                         p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
-                        try (
-                                JarFile jarFile = new JarFile(tmpfile.getCanonicalPath());
-                                OutputStream pack = new FileOutputStream(packFile)
-                        ) {
+                        try (JarFile jarFile = new JarFile(tmpfile.getCanonicalPath());
+                             OutputStream pack = new FileOutputStream(packFile))
+                        {
                             packer.pack(jarFile, pack);
                         }
                         if (tmpfile.exists()) {
                             tmpfile.delete();
                         }
                         tmpfile = createTemporaryFile(tmpbase, ".jar");
-                        try (
-                                OutputStream out = new FileOutputStream(tmpfile);
-                                JarOutputStream jos = new JarOutputStream(out)
-                        ) {
+                        try (OutputStream out = new FileOutputStream(tmpfile);
+                             JarOutputStream jos = new JarOutputStream(out))
+                        {
                             Unpacker unpacker = Pack200.newUnpacker();
                             unpacker.unpack(packFile, jos);
                         }
@@ -420,9 +332,7 @@
                         Files.deleteIfExists(packFile.toPath());
                     }
                 }
-
                 validateAndClose(tmpfile);
-
             } else if (uflag) {
                 File inputFile = null, tmpFile = null;
                 if (fname != null) {
@@ -432,39 +342,20 @@
                     vflag = false;
                     tmpFile = createTemporaryFile("tmpjar", ".jar");
                 }
-
-                Map<String,Path> moduleInfoPaths = new HashMap<>();
-                for (int version : filesMap.keySet()) {
-                    String[] files = filesMap.get(version);
-                    expand(null, files, true, moduleInfoPaths, version);
+                expand();
+                try (FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
+                        : new FileInputStream(FileDescriptor.in);
+                     FileOutputStream out = new FileOutputStream(tmpFile);
+                     InputStream manifest = (!Mflag && (mname != null)) ?
+                            (new FileInputStream(mname)) : null;
+                ) {
+                    boolean updateOk = update(in, new BufferedOutputStream(out),
+                        manifest, moduleInfos, null);
+                    if (ok) {
+                        ok = updateOk;
+                    }
                 }
-
-                Map<String,byte[]> moduleInfos = new HashMap<>();
-                for (Map.Entry<String,Path> e : moduleInfoPaths.entrySet())
-                    moduleInfos.put(e.getKey(), readModuleInfo(e.getValue()));
-
-                try (
-                        FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
-                                : new FileInputStream(FileDescriptor.in);
-                        FileOutputStream out = new FileOutputStream(tmpFile);
-                        InputStream manifest = (!Mflag && (mname != null)) ?
-                                (new FileInputStream(mname)) : null;
-                ) {
-                        boolean updateOk = update(in, new BufferedOutputStream(out),
-                                manifest, moduleInfos, null);
-                        if (ok) {
-                            ok = updateOk;
-                        }
-                }
-
-                // Consistency checks for modular jars.
-                if (!moduleInfos.isEmpty()) {
-                    if(!checkServices(moduleInfos.get(MODULE_INFO)))
-                        return false;
-                }
-
                 validateAndClose(tmpFile);
-
             } else if (tflag) {
                 replaceFSC(filesMap);
                 // For the "list table contents" action, access using the
@@ -542,12 +433,15 @@
 
     private void validateAndClose(File tmpfile) throws IOException {
         if (ok && isMultiRelease) {
-            ok = validate(tmpfile.getCanonicalPath());
-            if (!ok) {
-                error(formatMsg("error.validator.jarfile.invalid", fname));
+            try (JarFile jf = new JarFile(tmpfile)) {
+                ok = Validator.validate(this, jf);
+                if (!ok) {
+                    error(formatMsg("error.validator.jarfile.invalid", fname));
+                }
+            } catch (IOException e) {
+                error(formatMsg2("error.validator.jarfile.exception", fname, e.getMessage()));
             }
         }
-
         Path path = tmpfile.toPath();
         try {
             if (ok) {
@@ -572,78 +466,9 @@
 
     Stream<String> filesToEntryNames(Map.Entry<Integer,String[]> fileEntries) {
         int version = fileEntries.getKey();
+        Set<String> cpaths = pathsMap.get(version);
         return Stream.of(fileEntries.getValue())
-                .map(f -> (new EntryName(f, version)).entryName);
-    }
-
-    // sort base entries before versioned entries, and sort entry classes with
-    // nested classes so that the top level class appears before the associated
-    // nested class
-    private Comparator<JarEntry> entryComparator = (je1, je2) ->  {
-        String s1 = je1.getName();
-        String s2 = je2.getName();
-        if (s1.equals(s2)) return 0;
-        boolean b1 = s1.startsWith(VERSIONS_DIR);
-        boolean b2 = s2.startsWith(VERSIONS_DIR);
-        if (b1 && !b2) return 1;
-        if (!b1 && b2) return -1;
-        int n = 0; // starting char for String compare
-        if (b1 && b2) {
-            // normally strings would be sorted so "10" goes before "9", but
-            // version number strings need to be sorted numerically
-            n = VERSIONS_DIR.length();   // skip the common prefix
-            int i1 = s1.indexOf('/', n);
-            int i2 = s1.indexOf('/', n);
-            if (i1 == -1) throw new InvalidJarException(s1);
-            if (i2 == -1) throw new InvalidJarException(s2);
-            // shorter version numbers go first
-            if (i1 != i2) return i1 - i2;
-            // otherwise, handle equal length numbers below
-        }
-        int l1 = s1.length();
-        int l2 = s2.length();
-        int lim = Math.min(l1, l2);
-        for (int k = n; k < lim; k++) {
-            char c1 = s1.charAt(k);
-            char c2 = s2.charAt(k);
-            if (c1 != c2) {
-                // change natural ordering so '.' comes before '$'
-                // i.e. top level classes come before nested classes
-                if (c1 == '$' && c2 == '.') return 1;
-                if (c1 == '.' && c2 == '$') return -1;
-                return c1 - c2;
-            }
-        }
-        return l1 - l2;
-    };
-
-    private boolean validate(String fname) {
-        boolean valid;
-
-        try (JarFile jf = new JarFile(fname)) {
-            Validator validator = new Validator(this, jf);
-            jf.stream()
-                    .filter(e -> !e.isDirectory())
-                    .filter(e -> !e.getName().equals(MANIFEST_NAME))
-                    .filter(e -> !e.getName().endsWith(MODULE_INFO))
-                    .sorted(entryComparator)
-                    .forEachOrdered(validator);
-             valid = validator.isValid();
-        } catch (IOException e) {
-            error(formatMsg2("error.validator.jarfile.exception", fname, e.getMessage()));
-            valid = false;
-        } catch (InvalidJarException e) {
-            error(formatMsg("error.validator.bad.entry.name", e.getMessage()));
-            valid = false;
-        }
-        return valid;
-    }
-
-    private static class InvalidJarException extends RuntimeException {
-        private static final long serialVersionUID = -3642329147299217726L;
-        InvalidJarException(String msg) {
-            super(msg);
-        }
+            .map(f -> toVersionedName(toEntryName(f, cpaths, false), version));
     }
 
     /**
@@ -668,20 +493,22 @@
             // Note: flags.length == 2 can be treated as the short version of
             // the GNU option since the there cannot be any other options,
             // excluding -C, as per the old way.
-            if (flags.startsWith("--")
-                || (flags.startsWith("-") && flags.length() == 2)) {
+            if (flags.startsWith("--") ||
+                (flags.startsWith("-") && flags.length() == 2)) {
                 try {
                     count = GNUStyleOptions.parseOptions(this, args);
                 } catch (GNUStyleOptions.BadArgs x) {
                     if (info == null) {
-                        error(x.getMessage());
-                        if (x.showUsage)
-                            Info.USAGE_TRYHELP.print(err);
+                        if (x.showUsage) {
+                            usageError(x.getMessage());
+                        } else {
+                            error(x.getMessage());
+                        }
                         return false;
                     }
                 }
                 if (info != null) {
-                    info.print(out);
+                    info.accept(out);
                     return true;
                 }
             } else {
@@ -851,19 +678,55 @@
      * Add the package of the given resource name if it's a .class
      * or a resource in a named package.
      */
-    boolean addPackageIfNamed(String name) {
+    void addPackageIfNamed(Set<String> packages, String name) {
         if (name.startsWith(VERSIONS_DIR)) {
-            throw new InternalError(name);
+            // trim the version dir prefix
+            int i0 = VERSIONS_DIR.length();
+            int i = name.indexOf('/', i0);
+            if (i <= 0) {
+                warn(formatMsg("warn.release.unexpected.versioned.entry", name));
+                return;
+            }
+            while (i0 < i) {
+                char c = name.charAt(i0);
+                if (c < '0' || c > '9') {
+                    warn(formatMsg("warn.release.unexpected.versioned.entry", name));
+                    return;
+                }
+                i0++;
+            }
+            name = name.substring(i + 1, name.length());
         }
-
         String pn = toPackageName(name);
         // add if this is a class or resource in a package
         if (Checks.isJavaIdentifier(pn)) {
             packages.add(pn);
-            return true;
+        }
+    }
+
+    private String toEntryName(String name, Set<String> cpaths, boolean isDir) {
+        name = name.replace(File.separatorChar, '/');
+        if (isDir) {
+            name = name.endsWith("/") ? name : name + "/";
         }
+        String matchPath = "";
+        for (String path : cpaths) {
+            if (name.startsWith(path) && path.length() > matchPath.length()) {
+                matchPath = path;
+            }
+        }
+        name = safeName(name.substring(matchPath.length()));
+        // the old implementaton doesn't remove
+        // "./" if it was led by "/" (?)
+        if (name.startsWith("./")) {
+            name = name.substring(2);
+        }
+        return name;
+    }
 
-        return false;
+    private static String toVersionedName(String name, int version) {
+        return version > BASE_VERSION
+                ? VERSIONS_DIR + version + "/" + name : name;
     }
 
     private static String toPackageName(String path) {
@@ -875,57 +738,23 @@
         }
     }
 
-    /*
-     * Returns true if the given entry is a valid entry of the given version.
-     */
-    private boolean isValidVersionedEntry(Entry entry, int version) {
-        String name = entry.basename;
-        if (name.startsWith(VERSIONS_DIR) && version != BASE_VERSION) {
-            int i = name.indexOf('/', VERSIONS_DIR.length());
-            // name == -1 -> not a versioned directory, something else
-            if (i == -1)
-                return false;
-            try {
-                String v = name.substring(VERSIONS_DIR.length(), i);
-                return Integer.valueOf(v) == version;
-            } catch (NumberFormatException x) {
-                return false;
-            }
+    private void expand() throws IOException {
+        for (int version : filesMap.keySet()) {
+            String[] files = filesMap.get(version);
+            expand(null, files, pathsMap.get(version), version);
         }
-        return true;
-    }
-
-    /*
-     * Trim META-INF/versions/$version/ from the given name if the
-     * given name is a versioned entry of the given version; or
-     * of any version if the given version is BASE_VERSION
-     */
-    private String trimVersionsDir(String name, int version) {
-        if (name.startsWith(VERSIONS_DIR)) {
-            int i = name.indexOf('/', VERSIONS_DIR.length());
-            if (i >= 0) {
-                try {
-                    String v = name.substring(VERSIONS_DIR.length(), i);
-                    if (version == BASE_VERSION || Integer.valueOf(v) == version) {
-                        return name.substring(i + 1, name.length());
-                    }
-                } catch (NumberFormatException x) {}
-            }
-            throw new InternalError("unexpected versioned entry: " +
-                    name + " version " + version);
-        }
-        return name;
     }
 
     /**
      * Expands list of files to process into full list of all files that
      * can be found by recursively descending directories.
+     *
+     * @param dir    parent directory
+     * @param file s list of files to expand
+     * @param cpaths set of directories specified by -C option for the files
+     * @throws IOException if an I/O error occurs
      */
-    void expand(File dir,
-                String[] files,
-                boolean isUpdate,
-                Map<String,Path> moduleInfoPaths,
-                int version)
+    private void expand(File dir, String[] files, Set<String> cpaths, int version)
         throws IOException
     {
         if (files == null)
@@ -938,47 +767,48 @@
             else
                 f = new File(dir, files[i]);
 
-            Entry e = new Entry(version, f);
-            String entryName = e.entryname;
-            Entry entry = e;
-            if (e.basename.startsWith(VERSIONS_DIR) && isValidVersionedEntry(e, version)) {
-                entry = e.toVersionedEntry(version);
-            }
-            if (f.isFile()) {
-                if (entryName.endsWith(MODULE_INFO)) {
-                    moduleInfoPaths.put(entryName, f.toPath());
-                    if (isUpdate)
-                        entryMap.put(entryName, entry);
-                } else if (isValidVersionedEntry(entry, version)) {
-                    if (entries.add(entry)) {
-                        jarEntries.add(entryName);
-                        // add the package if it's a class or resource
-                        addPackageIfNamed(trimVersionsDir(entry.basename, version));
-                        if (isUpdate)
-                            entryMap.put(entryName, entry);
-                    }
-                } else {
+            boolean isDir = f.isDirectory();
+            String name = toEntryName(f.getPath(), cpaths, isDir);
+
+            if (version != BASE_VERSION) {
+                if (name.startsWith(VERSIONS_DIR)) {
+                    // the entry starts with VERSIONS_DIR and version != BASE_VERSION,
+                    // which means the "[dirs|files]" in --release v [dirs|files]
+                    // includes VERSIONS_DIR-ed entries --> warning and skip (?)
                     error(formatMsg2("error.release.unexpected.versioned.entry",
-                                      entry.basename, String.valueOf(version)));
+                                     name, String.valueOf(version)));
                     ok = false;
+                    return;
                 }
-            } else if (f.isDirectory()) {
-                if (isValidVersionedEntry(entry, version)) {
-                    if (entries.add(entry)) {
-                        if (isUpdate) {
-                            entryMap.put(entryName, entry);
-                        }
+                name = toVersionedName(name, version);
+            }
+
+            if (f.isFile()) {
+                Entry e = new Entry(f, name, false);
+                if (isModuleInfoEntry(name)) {
+                    moduleInfos.putIfAbsent(name, Files.readAllBytes(f.toPath()));
+                    if (uflag)
+                        entryMap.put(name, e);
+                } else if (entries.add(e)) {
+                    if (uflag)
+                        entryMap.put(name, e);
+                }
+            } else if (isDir) {
+                Entry e = new Entry(f, name, true);
+                if (entries.add(e)) {
+                    // utilize entryMap for the duplicate dir check even in
+                    // case of cflag == true.
+                    // dir name confilict/duplicate could happen with -C option.
+                    // just remove the last "e" from the "entries" (zos will fail
+                    // with "duplicated" entries), but continue expanding the
+                    // sub tree
+                    if (entryMap.containsKey(name)) {
+                        entries.remove(e);
+                    } else {
+                        entryMap.put(name, e);
                     }
-                } else if (entry.basename.equals(VERSIONS_DIR)) {
-                    if (vflag) {
-                        output(formatMsg("out.ignore.entry", entry.basename));
-                    }
-                } else {
-                    error(formatMsg2("error.release.unexpected.versioned.entry",
-                                      entry.basename, String.valueOf(version)));
-                    ok = false;
+                    expand(f, f.list(), cpaths, version);
                 }
-                expand(f, f.list(), isUpdate, moduleInfoPaths, version);
             } else {
                 error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
                 ok = false;
@@ -989,52 +819,36 @@
     /**
      * Creates a new JAR file.
      */
-    void create(OutputStream out, Manifest manifest, Map<String,byte[]> moduleInfos)
-        throws IOException
+    void create(OutputStream out, Manifest manifest) throws IOException
     {
-        ZipOutputStream zos = new JarOutputStream(out);
-        if (flag0) {
-            zos.setMethod(ZipOutputStream.STORED);
-        }
-        // TODO: check module-info attributes against manifest ??
-        if (manifest != null) {
-            if (vflag) {
-                output(getMsg("out.added.manifest"));
-            }
-            ZipEntry e = new ZipEntry(MANIFEST_DIR);
-            e.setTime(System.currentTimeMillis());
-            e.setSize(0);
-            e.setCrc(0);
-            zos.putNextEntry(e);
-            e = new ZipEntry(MANIFEST_NAME);
-            e.setTime(System.currentTimeMillis());
+        try (ZipOutputStream zos = new JarOutputStream(out)) {
             if (flag0) {
-                crc32Manifest(e, manifest);
+                zos.setMethod(ZipOutputStream.STORED);
             }
-            zos.putNextEntry(e);
-            manifest.write(zos);
-            zos.closeEntry();
-        }
-        for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
-            String entryName = mi.getKey();
-            byte[] miBytes = mi.getValue();
-            if (vflag) {
-                output(formatMsg("out.added.module-info", entryName));
+            // TODO: check module-info attributes against manifest ??
+            if (manifest != null) {
+                if (vflag) {
+                    output(getMsg("out.added.manifest"));
+                }
+                ZipEntry e = new ZipEntry(MANIFEST_DIR);
+                e.setTime(System.currentTimeMillis());
+                e.setSize(0);
+                e.setCrc(0);
+                zos.putNextEntry(e);
+                e = new ZipEntry(MANIFEST_NAME);
+                e.setTime(System.currentTimeMillis());
+                if (flag0) {
+                    crc32Manifest(e, manifest);
+                }
+                zos.putNextEntry(e);
+                manifest.write(zos);
+                zos.closeEntry();
             }
-            ZipEntry e = new ZipEntry(mi.getKey());
-            e.setTime(System.currentTimeMillis());
-            if (flag0) {
-                crc32ModuleInfo(e, miBytes);
+            updateModuleInfo(moduleInfos, zos);
+            for (Entry entry : entries) {
+                addFile(zos, entry);
             }
-            zos.putNextEntry(e);
-            ByteArrayInputStream in = new ByteArrayInputStream(miBytes);
-            in.transferTo(zos);
-            zos.closeEntry();
         }
-        for (Entry entry : entries) {
-            addFile(zos, entry);
-        }
-        zos.close();
     }
 
     private char toUpperCaseASCII(char c) {
@@ -1062,30 +876,6 @@
     }
 
     /**
-     * Returns true of the given module-info's are located in acceptable
-     * locations.  Otherwise, outputs an appropriate message and returns false.
-     */
-    private boolean checkModuleInfos(Map<String,?> moduleInfos) {
-        // there must always be, at least, a root module-info
-        if (!moduleInfos.containsKey(MODULE_INFO)) {
-            error(getMsg("error.versioned.info.without.root"));
-            return false;
-        }
-
-        // module-info can only appear in the root, or a versioned section
-        Optional<String> other = moduleInfos.keySet().stream()
-                .filter(x -> !x.equals(MODULE_INFO))
-                .filter(x -> !x.startsWith(VERSIONS_DIR))
-                .findFirst();
-
-        if (other.isPresent()) {
-            error(formatMsg("error.unexpected.module-info", other.get()));
-            return false;
-        }
-        return true;
-    }
-
-    /**
      * Updates an existing jar file.
      */
     boolean update(InputStream in, OutputStream out,
@@ -1099,6 +889,10 @@
         boolean foundManifest = false;
         boolean updateOk = true;
 
+        // All actual entries added/updated/existing, in the jar file (excl manifest
+        // and module-info.class ).
+        Set<String> jentries = new HashSet<>();
+
         if (jarIndex != null) {
             addIndex(jarIndex, zos);
         }
@@ -1108,7 +902,7 @@
             String name = e.getName();
 
             boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
-            boolean isModuleInfoEntry = name.endsWith(MODULE_INFO);
+            boolean isModuleInfoEntry = isModuleInfoEntry(name);
 
             if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
                 || (Mflag && isManifestEntry)) {
@@ -1127,7 +921,6 @@
                         return false;
                     }
                 }
-
                 // Update the manifest.
                 Manifest old = new Manifest(zis);
                 if (newManifest != null) {
@@ -1137,7 +930,7 @@
                     return false;
                 }
             } else if (moduleInfos != null && isModuleInfoEntry) {
-                moduleInfos.putIfAbsent(name, readModuleInfo(zis));
+                moduleInfos.putIfAbsent(name, zis.readAllBytes());
             } else {
                 boolean isDir = e.isDirectory();
                 if (!entryMap.containsKey(name)) { // copy the old stuff
@@ -1160,11 +953,8 @@
                     entries.remove(ent);
                     isDir = ent.isDir;
                 }
-
-                jarEntries.add(name);
                 if (!isDir) {
-                    // add the package if it's a class or resource
-                    addPackageIfNamed(trimVersionsDir(name, BASE_VERSION));
+                    jentries.add(name);
                 }
             }
         }
@@ -1172,6 +962,9 @@
         // add the remaining new files
         for (Entry entry : entries) {
             addFile(zos, entry);
+            if (!entry.isDir) {
+                jentries.add(entry.name);
+            }
         }
         if (!foundManifest) {
             if (newManifest != null) {
@@ -1188,35 +981,24 @@
                 }
             }
         }
-
-        if (moduleInfos != null && !moduleInfos.isEmpty()) {
-            if (!checkModuleInfos(moduleInfos))
+        if (updateOk) {
+            if (moduleInfos != null && !moduleInfos.isEmpty()) {
+                Set<String> pkgs = new HashSet<>();
+                jentries.forEach( je -> addPackageIfNamed(pkgs, je));
+                addExtendedModuleAttributes(moduleInfos, pkgs);
+                updateOk = checkModuleInfo(moduleInfos.get(MODULE_INFO), jentries);
+                updateModuleInfo(moduleInfos, zos);
+                // TODO: check manifest main classes, etc
+            } else if (moduleVersion != null || modulesToHash != null) {
+                error(getMsg("error.module.options.without.info"));
                 updateOk = false;
-
-            if (updateOk) {
-                if (!addExtendedModuleAttributes(moduleInfos))
-                    updateOk = false;
             }
-
-            // TODO: check manifest main classes, etc
-
-            if (updateOk) {
-                for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
-                    if (!updateModuleInfo(mi.getValue(), zos, mi.getKey()))
-                        updateOk = false;
-                }
-            }
-        } else if (moduleVersion != null || modulesToHash != null) {
-            error(getMsg("error.module.options.without.info"));
-            updateOk = false;
         }
-
         zis.close();
         zos.close();
         return updateOk;
     }
 
-
     private void addIndex(JarIndex index, ZipOutputStream zos)
         throws IOException
     {
@@ -1232,20 +1014,25 @@
         zos.closeEntry();
     }
 
-    private boolean updateModuleInfo(byte[] moduleInfoBytes, ZipOutputStream zos, String entryName)
+    private void updateModuleInfo(Map<String,byte[]> moduleInfos, ZipOutputStream zos)
         throws IOException
     {
-        ZipEntry e = new ZipEntry(entryName);
-        e.setTime(System.currentTimeMillis());
-        if (flag0) {
-            crc32ModuleInfo(e, moduleInfoBytes);
+        String fmt = uflag ? "out.update.module-info": "out.added.module-info";
+        for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
+            String name = mi.getKey();
+            byte[] bytes = mi.getValue();
+            ZipEntry e = new ZipEntry(name);
+            e.setTime(System.currentTimeMillis());
+            if (flag0) {
+                crc32ModuleInfo(e, bytes);
+            }
+            zos.putNextEntry(e);
+            zos.write(bytes);
+            zos.closeEntry();
+            if (vflag) {
+                output(formatMsg(fmt, name));
+            }
         }
-        zos.putNextEntry(e);
-        zos.write(moduleInfoBytes);
-        if (vflag) {
-            output(formatMsg("out.update.module-info", entryName));
-        }
-        return true;
     }
 
     private boolean updateManifest(Manifest m, ZipOutputStream zos)
@@ -1358,11 +1145,9 @@
      * Adds a new file entry to the ZIP output stream.
      */
     void addFile(ZipOutputStream zos, Entry entry) throws IOException {
-        // skip the generation of directory entries for META-INF/versions/*/
-        if (entry.basename.isEmpty()) return;
 
         File file = entry.file;
-        String name = entry.entryname;
+        String name = entry.name;
         boolean isDir = entry.isDir;
 
         if (name.equals("") || name.equals(".") || name.equals(zname)) {
@@ -1444,11 +1229,8 @@
      * @throws IOException if an I/O error occurs
      */
     private void copy(File from, OutputStream to) throws IOException {
-        InputStream in = new FileInputStream(from);
-        try {
+        try (InputStream in = new FileInputStream(from)) {
             copy(in, to);
-        } finally {
-            in.close();
         }
     }
 
@@ -1461,11 +1243,8 @@
      * @throws IOException if an I/O error occurs
      */
     private void copy(InputStream from, File to) throws IOException {
-        OutputStream out = new FileOutputStream(to);
-        try {
+        try (OutputStream out = new FileOutputStream(to)) {
             copy(from, out);
-        } finally {
-            out.close();
         }
     }
 
@@ -1825,7 +1604,7 @@
      */
     void usageError(String s) {
         err.println(s);
-        Info.USAGE_TRYHELP.print(err);
+        err.println(getMsg("main.usage.summary.try"));
     }
 
     /**
@@ -1934,16 +1713,6 @@
         return tmpfile;
     }
 
-    private static byte[] readModuleInfo(InputStream zis) throws IOException {
-        return zis.readAllBytes();
-    }
-
-    private static byte[] readModuleInfo(Path path) throws IOException {
-        try (InputStream is = Files.newInputStream(path)) {
-            return is.readAllBytes();
-        }
-    }
-
     // Modular jar support
 
     static <T> String toString(Collection<T> c,
@@ -1951,7 +1720,6 @@
                                CharSequence suffix ) {
         if (c.isEmpty())
             return "";
-
         return c.stream().map(e -> e.toString())
                            .collect(joining(", ", prefix, suffix));
     }
@@ -2045,136 +1813,84 @@
 
         md.osVersion().ifPresent(v -> sb.append("\n  operating-system-version " + v));
 
-        if (hashes != null) {
-            hashes.names().stream().sorted().forEach(
-                    mod -> sb.append("\n  hashes ").append(mod).append(" ")
-                             .append(hashes.algorithm()).append(" ")
-                             .append(toHex(hashes.hashFor(mod))));
+       if (hashes != null) {
+           hashes.names().stream().sorted().forEach(
+                   mod -> sb.append("\n  hashes ").append(mod).append(" ")
+                            .append(hashes.algorithm()).append(" ")
+                            .append(toHex(hashes.hashFor(mod))));
         }
 
         output(sb.toString());
     }
 
     private static String toHex(byte[] ba) {
-        StringBuilder sb = new StringBuilder(ba.length);
+        StringBuilder sb = new StringBuilder(ba.length << 1);
         for (byte b: ba) {
             sb.append(String.format("%02x", b & 0xff));
         }
         return sb.toString();
     }
 
-    private static String toBinaryName(String classname) {
+    static String toBinaryName(String classname) {
         return (classname.replace('.', '/')) + ".class";
     }
 
-    /* A module must have the implementation class of the services it 'provides'. */
-    private boolean checkServices(byte[] moduleInfoBytes)
+    private boolean checkModuleInfo(byte[] moduleInfoBytes, Set<String> entries)
         throws IOException
     {
-        ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
-        Set<String> missing = md.provides()
-                                .stream()
-                                .map(Provides::providers)
-                                .flatMap(List::stream)
-                                .filter(p -> !jarEntries.contains(toBinaryName(p)))
-                                .collect(Collectors.toSet());
-        if (missing.size() > 0) {
-            missing.stream().forEach(s -> fatalError(formatMsg("error.missing.provider", s)));
-            return false;
+        boolean ok = true;
+        if (moduleInfoBytes != null) {  // no root module-info.class if null
+            try {
+                // ModuleDescriptor.read() checks open/exported pkgs vs packages
+                ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
+                // A module must have the implementation class of the services it 'provides'.
+                if (md.provides().stream().map(Provides::providers).flatMap(List::stream)
+                      .filter(p -> !entries.contains(toBinaryName(p)))
+                      .peek(p -> fatalError(formatMsg("error.missing.provider", p)))
+                      .count() != 0) {
+                    ok = false;
+                }
+            } catch (InvalidModuleDescriptorException x) {
+                fatalError(x.getMessage());
+                ok = false;
+            }
         }
-        return true;
+        return ok;
     }
 
     /**
      * Adds extended modules attributes to the given module-info's.  The given
      * Map values are updated in-place. Returns false if an error occurs.
      */
-    private boolean addExtendedModuleAttributes(Map<String,byte[]> moduleInfos)
+    private void addExtendedModuleAttributes(Map<String,byte[]> moduleInfos,
+                                                Set<String> packages)
         throws IOException
     {
-        assert !moduleInfos.isEmpty() && moduleInfos.get(MODULE_INFO) != null;
-
-        ByteBuffer bb = ByteBuffer.wrap(moduleInfos.get(MODULE_INFO));
-        ModuleDescriptor rd = ModuleDescriptor.read(bb);
-
-        concealedPackages = findConcealedPackages(rd);
-
         for (Map.Entry<String,byte[]> e: moduleInfos.entrySet()) {
-            ModuleDescriptor vd = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
-            if (!(isValidVersionedDescriptor(vd, rd)))
-                return false;
-            e.setValue(extendedInfoBytes(rd, vd, e.getValue(), packages));
+            ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
+            e.setValue(extendedInfoBytes(md, e.getValue(), packages));
         }
-        return true;
-    }
-
-    private Set<String> findConcealedPackages(ModuleDescriptor md) {
-        Objects.requireNonNull(md);
-        Set<String> concealed = new HashSet<>(packages);
-        md.exports().stream().map(Exports::source).forEach(concealed::remove);
-        md.opens().stream().map(Opens::source).forEach(concealed::remove);
-        return concealed;
-    }
-
-    private static boolean isPlatformModule(String name) {
-        return name.startsWith("java.") || name.startsWith("jdk.");
     }
 
-    /**
-     * Tells whether or not the given versioned module descriptor's attributes
-     * are valid when compared against the given root module descriptor.
-     *
-     * A versioned module descriptor must be identical to the root module
-     * descriptor, with two exceptions:
-     *  - A versioned descriptor can have different non-public `requires`
-     *    clauses of platform ( `java.*` and `jdk.*` ) modules, and
-     *  - A versioned descriptor can have different `uses` clauses, even of
-     *    service types defined outside of the platform modules.
-     */
-    private boolean isValidVersionedDescriptor(ModuleDescriptor vd,
-                                               ModuleDescriptor rd)
-        throws IOException
-    {
-        if (!rd.name().equals(vd.name())) {
-            fatalError(getMsg("error.versioned.info.name.notequal"));
-            return false;
-        }
-        if (!rd.requires().equals(vd.requires())) {
-            Set<Requires> rootRequires = rd.requires();
-            for (Requires r : vd.requires()) {
-                if (rootRequires.contains(r)) {
-                    continue;
-                } else if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) {
-                    fatalError(getMsg("error.versioned.info.requires.transitive"));
+    static boolean isModuleInfoEntry(String name) {
+        // root or versioned module-info.class
+        if (name.endsWith(MODULE_INFO)) {
+            int end = name.length() - MODULE_INFO.length();
+            if (end == 0)
+                return true;
+            if (name.startsWith(VERSIONS_DIR)) {
+                int off = VERSIONS_DIR.length();
+                if (off == end)      // meta-inf/versions/module-info.class
                     return false;
-                } else if (!isPlatformModule(r.name())) {
-                    fatalError(getMsg("error.versioned.info.requires.added"));
-                    return false;
+                while (off < end - 1) {
+                    char c = name.charAt(off++);
+                    if (c < '0' || c > '9')
+                        return false;
                 }
-            }
-            for (Requires r : rootRequires) {
-                Set<Requires> mdRequires = vd.requires();
-                if (mdRequires.contains(r)) {
-                    continue;
-                } else if (!isPlatformModule(r.name())) {
-                    fatalError(getMsg("error.versioned.info.requires.dropped"));
-                    return false;
-                }
+                return name.charAt(off) == '/';
             }
         }
-        if (!rd.exports().equals(vd.exports())) {
-            fatalError(getMsg("error.versioned.info.exports.notequal"));
-            return false;
-        }
-        if (!rd.opens().equals(vd.opens())) {
-            fatalError(getMsg("error.versioned.info.opens.notequal"));
-            return false;
-        }
-        if (!rd.provides().equals(vd.provides())) {
-            fatalError(getMsg("error.versioned.info.provides.notequal"));
-            return false;
-        }
-        return true;
+        return false;
     }
 
     /**
@@ -2185,8 +1901,7 @@
      * then the corresponding class file attributes are added to the
      * module-info here.
      */
-    private byte[] extendedInfoBytes(ModuleDescriptor rootDescriptor,
-                                     ModuleDescriptor md,
+    private byte[] extendedInfoBytes(ModuleDescriptor md,
                                      byte[] miBytes,
                                      Set<String> packages)
         throws IOException
@@ -2201,14 +1916,10 @@
         // --main-class
         if (ename != null)
             extender.mainClass(ename);
-        else if (rootDescriptor.mainClass().isPresent())
-            extender.mainClass(rootDescriptor.mainClass().get());
 
         // --module-version
         if (moduleVersion != null)
             extender.version(moduleVersion);
-        else if (rootDescriptor.version().isPresent())
-            extender.version(rootDescriptor.version().get());
 
         // --hash-modules
         if (modulesToHash != null) {
@@ -2218,8 +1929,7 @@
             if (moduleHashes != null) {
                 extender.hashes(moduleHashes);
             } else {
-                // should it issue warning or silent?
-                System.out.println("warning: no module is recorded in hash in " + mn);
+                warn("warning: no module is recorded in hash in " + mn);
             }
         }
 
@@ -2235,10 +1945,9 @@
      * Compute and record hashes
      */
     private class Hasher {
+        final ModuleHashesBuilder hashesBuilder;
         final ModuleFinder finder;
-        final Map<String, Path> moduleNameToPath;
         final Set<String> modules;
-        final Configuration configuration;
         Hasher(ModuleDescriptor descriptor, String fname) throws IOException {
             // Create a module finder that finds the modular JAR
             // being created/updated
@@ -2268,119 +1977,46 @@
                     }
                 });
 
-            // Determine the modules that matches the modulesToHash pattern
-            this.modules = moduleFinder.findAll().stream()
-                .map(moduleReference -> moduleReference.descriptor().name())
+            // Determine the modules that matches the pattern {@code modulesToHash}
+            Set<String> roots = finder.findAll().stream()
+                .map(ref -> ref.descriptor().name())
                 .filter(mn -> modulesToHash.matcher(mn).find())
                 .collect(Collectors.toSet());
 
-            // a map from a module name to Path of the modular JAR
-            this.moduleNameToPath = moduleFinder.findAll().stream()
-                .map(ModuleReference::descriptor)
-                .map(ModuleDescriptor::name)
-                .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
-
-            Configuration config = null;
-            try {
-                config = Configuration.empty()
-                    .resolveRequires(ModuleFinder.ofSystem(), finder, modules);
-            } catch (ResolutionException e) {
-                // should it throw an error?  or emit a warning
-                System.out.println("warning: " + e.getMessage());
+            // use system module path unless it creates a modular JAR for
+            // a module that is present in the system image e.g. upgradeable
+            // module
+            ModuleFinder system;
+            String name = descriptor.name();
+            if (name != null && ModuleFinder.ofSystem().find(name).isPresent()) {
+                system = ModuleFinder.of();
+            } else {
+                system = ModuleFinder.ofSystem();
             }
-            this.configuration = config;
-        }
+            // get a resolved module graph
+            Configuration config =
+                Configuration.empty().resolveRequires(system, finder, roots);
 
-        /**
-         * Compute hashes of the modules that depend upon the specified
-         * module directly or indirectly.
-         */
-        ModuleHashes computeHashes(String name) {
-            // the transposed graph includes all modules in the resolved graph
-            Map<String, Set<String>> graph = transpose();
+            // filter modules resolved from the system module finder
+            this.modules = config.modules().stream()
+                .map(ResolvedModule::name)
+                .filter(mn -> roots.contains(mn) && !system.find(mn).isPresent())
+                .collect(Collectors.toSet());
 
-            // find the modules that transitively depend upon the specified name
-            Deque<String> deque = new ArrayDeque<>();
-            deque.add(name);
-            Set<String> mods = visitNodes(graph, deque);
-
-            // filter modules matching the pattern specified in --hash-modules,
-            // as well as the modular jar file that is being created / updated
-            Map<String, Path> modulesForHash = mods.stream()
-                .filter(mn -> !mn.equals(name) && modules.contains(mn))
-                .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
-
-            if (modulesForHash.isEmpty())
-                return null;
-
-            return ModuleHashes.generate(modulesForHash, "SHA-256");
+            this.hashesBuilder = new ModuleHashesBuilder(config, modules);
         }
 
         /**
-         * Returns all nodes traversed from the given roots.
+         * Compute hashes of the specified module.
+         *
+         * It records the hashing modules that depend upon the specified
+         * module directly or indirectly.
          */
-        private Set<String> visitNodes(Map<String, Set<String>> graph,
-                                       Deque<String> roots) {
-            Set<String> visited = new HashSet<>();
-            while (!roots.isEmpty()) {
-                String mn = roots.pop();
-                if (!visited.contains(mn)) {
-                    visited.add(mn);
-
-                    // the given roots may not be part of the graph
-                    if (graph.containsKey(mn)) {
-                        for (String dm : graph.get(mn)) {
-                            if (!visited.contains(dm))
-                                roots.push(dm);
-                        }
-                    }
-                }
-            }
-            return visited;
-        }
-
-        /**
-         * Returns a transposed graph from the resolved module graph.
-         */
-        private Map<String, Set<String>> transpose() {
-            Map<String, Set<String>> transposedGraph = new HashMap<>();
-            Deque<String> deque = new ArrayDeque<>(modules);
+        ModuleHashes computeHashes(String name) {
+            if (hashesBuilder == null)
+                return null;
 
-            Set<String> visited = new HashSet<>();
-            while (!deque.isEmpty()) {
-                String mn = deque.pop();
-                if (!visited.contains(mn)) {
-                    visited.add(mn);
-
-                    // add an empty set
-                    transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
-
-                    ResolvedModule resolvedModule = configuration.findModule(mn).get();
-                    for (ResolvedModule dm : resolvedModule.reads()) {
-                        String name = dm.name();
-                        if (!visited.contains(name)) {
-                            deque.push(name);
-                        }
-                        // reverse edge
-                        transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
-                                       .add(mn);
-                    }
-                }
-            }
-            return transposedGraph;
-        }
-
-        private Path moduleToPath(String name) {
-            ModuleReference mref = moduleFinder.find(name).orElseThrow(
-                () -> new InternalError(formatMsg2("error.hash.dep",name , name)));
-
-            URI uri = mref.location().get();
-            Path path = Paths.get(uri);
-            String fn = path.getFileName().toString();
-            if (!fn.endsWith(".jar")) {
-                throw new UnsupportedOperationException(path + " is not a modular JAR");
-            }
-            return path;
+            return hashesBuilder.computeHashes(Set.of(name)).get(name);
         }
     }
 }
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  * 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,32 +25,120 @@
 
 package sun.tools.jar;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.InvalidModuleDescriptorException;
+import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Consumer;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
 
-final class Validator implements Consumer<JarEntry> {
+import static java.util.jar.JarFile.MANIFEST_NAME;
+import static sun.tools.jar.Main.VERSIONS_DIR;
+import static sun.tools.jar.Main.MODULE_INFO;
+import static sun.tools.jar.Main.getMsg;
+import static sun.tools.jar.Main.formatMsg;
+import static sun.tools.jar.Main.formatMsg2;
+import static sun.tools.jar.Main.toBinaryName;
+import static sun.tools.jar.Main.isModuleInfoEntry;
+
+final class Validator {
     private final static boolean DEBUG = Boolean.getBoolean("jar.debug");
     private final  Map<String,FingerPrint> fps = new HashMap<>();
-    private final int vdlen = Main.VERSIONS_DIR.length();
+    private static final int vdlen = VERSIONS_DIR.length();
     private final Main main;
     private final JarFile jf;
     private int oldVersion = -1;
     private String currentTopLevelName;
     private boolean isValid = true;
+    private Set<String> concealedPkgs;
+    private ModuleDescriptor md;
 
-    Validator(Main main, JarFile jf) {
+    private Validator(Main main, JarFile jf) {
         this.main = main;
         this.jf = jf;
+        loadModuleDescriptor();
+    }
+
+    static boolean validate(Main main, JarFile jf) throws IOException {
+        return new Validator(main, jf).validate();
+    }
+
+    private boolean validate() {
+        try {
+            jf.stream()
+              .filter(e -> !e.isDirectory() &&
+                      !e.getName().equals(MANIFEST_NAME))
+              .sorted(entryComparator)
+              .forEachOrdered(e -> validate(e));
+            return isValid;
+        } catch (InvalidJarException e) {
+            error(formatMsg("error.validator.bad.entry.name", e.getMessage()));
+        }
+        return false;
+    }
+
+    private static class InvalidJarException extends RuntimeException {
+        private static final long serialVersionUID = -3642329147299217726L;
+        InvalidJarException(String msg) {
+            super(msg);
+        }
     }
 
-    boolean isValid() {
-        return isValid;
-    }
+    // sort base entries before versioned entries, and sort entry classes with
+    // nested classes so that the top level class appears before the associated
+    // nested class
+    private static Comparator<JarEntry> entryComparator = (je1, je2) ->  {
+        String s1 = je1.getName();
+        String s2 = je2.getName();
+        if (s1.equals(s2)) return 0;
+        boolean b1 = s1.startsWith(VERSIONS_DIR);
+        boolean b2 = s2.startsWith(VERSIONS_DIR);
+        if (b1 && !b2) return 1;
+        if (!b1 && b2) return -1;
+        int n = 0; // starting char for String compare
+        if (b1 && b2) {
+            // normally strings would be sorted so "10" goes before "9", but
+            // version number strings need to be sorted numerically
+            n = VERSIONS_DIR.length();   // skip the common prefix
+            int i1 = s1.indexOf('/', n);
+            int i2 = s1.indexOf('/', n);
+            if (i1 == -1) throw new InvalidJarException(s1);
+            if (i2 == -1) throw new InvalidJarException(s2);
+            // shorter version numbers go first
+            if (i1 != i2) return i1 - i2;
+            // otherwise, handle equal length numbers below
+        }
+        int l1 = s1.length();
+        int l2 = s2.length();
+        int lim = Math.min(l1, l2);
+        for (int k = n; k < lim; k++) {
+            char c1 = s1.charAt(k);
+            char c2 = s2.charAt(k);
+            if (c1 != c2) {
+                // change natural ordering so '.' comes before '$'
+                // i.e. top level classes come before nested classes
+                if (c1 == '$' && c2 == '.') return 1;
+                if (c1 == '.' && c2 == '$') return -1;
+                return c1 - c2;
+            }
+        }
+        return l1 - l2;
+    };
 
     /*
      *  Validator has state and assumes entries provided to accept are ordered
@@ -59,7 +147,7 @@
      *  classes must be ordered so that the top level class is before the associated
      *  nested class(es).
     */
-    public void accept(JarEntry je) {
+    public void validate(JarEntry je) {
         String entryName = je.getName();
 
         // directories are always accepted
@@ -68,13 +156,20 @@
             return;
         }
 
+        // validate the versioned module-info
+        if (isModuleInfoEntry(entryName)) {
+            if (entryName.length() != MODULE_INFO.length())
+                checkModuleDescriptor(je);
+            return;
+        }
+
         // figure out the version and basename from the JarEntry
         int version;
         String basename;
-        if (entryName.startsWith(Main.VERSIONS_DIR)) {
+        if (entryName.startsWith(VERSIONS_DIR)) {
             int n = entryName.indexOf("/", vdlen);
             if (n == -1) {
-                main.error(Main.formatMsg("error.validator.version.notnumber", entryName));
+                error(formatMsg("error.validator.version.notnumber", entryName));
                 isValid = false;
                 return;
             }
@@ -82,12 +177,12 @@
             try {
                 version = Integer.parseInt(v);
             } catch (NumberFormatException x) {
-                main.error(Main.formatMsg("error.validator.version.notnumber", entryName));
+                error(formatMsg("error.validator.version.notnumber", entryName));
                 isValid = false;
                 return;
             }
             if (n == entryName.length()) {
-                main.error(Main.formatMsg("error.validator.entryname.tooshort", entryName));
+                error(formatMsg("error.validator.entryname.tooshort", entryName));
                 isValid = false;
                 return;
             }
@@ -108,7 +203,7 @@
         try (InputStream is = jf.getInputStream(je)) {
             fp = new FingerPrint(basename, is.readAllBytes());
         } catch (IOException x) {
-            main.error(x.getMessage());
+            error(x.getMessage());
             isValid = false;
             return;
         }
@@ -123,7 +218,7 @@
                     fps.put(internalName, fp);
                     return;
                 }
-                main.error(Main.formatMsg("error.validator.isolated.nested.class", entryName));
+                error(formatMsg("error.validator.isolated.nested.class", entryName));
                 isValid = false;
                 return;
             }
@@ -153,11 +248,11 @@
                 }
                 if (fp.isPublicClass()) {
                     if (!isConcealed(internalName)) {
-                        main.error(Main.formatMsg("error.validator.new.public.class", entryName));
+                        error(Main.formatMsg("error.validator.new.public.class", entryName));
                         isValid = false;
                         return;
                     }
-                    main.warn(Main.formatMsg("warn.validator.concealed.public.class", entryName));
+                    warn(formatMsg("warn.validator.concealed.public.class", entryName));
                     debug("%s is a public class entry in a concealed package", entryName);
                 }
                 debug("%s is a non-public class entry", entryName);
@@ -173,7 +268,7 @@
 
         // are the two classes/resources identical?
         if (fp.isIdentical(matchFp)) {
-            main.warn(Main.formatMsg("warn.validator.identical.entry", entryName));
+            warn(formatMsg("warn.validator.identical.entry", entryName));
             return;  // it's okay, just takes up room
         }
         debug("sha1 not equal -- different bytes");
@@ -188,12 +283,12 @@
             }
             debug("%s is a class entry", entryName);
             if (!fp.isCompatibleVersion(matchFp)) {
-                main.error(Main.formatMsg("error.validator.incompatible.class.version", entryName));
+                error(formatMsg("error.validator.incompatible.class.version", entryName));
                 isValid = false;
                 return;
             }
             if (!fp.isSameAPI(matchFp)) {
-                main.error(Main.formatMsg("error.validator.different.api", entryName));
+                error(formatMsg("error.validator.different.api", entryName));
                 isValid = false;
                 return;
             }
@@ -208,17 +303,118 @@
         }
         debug("%s is a resource", entryName);
 
-        main.warn(Main.formatMsg("warn.validator.resources.with.same.name", entryName));
+        warn(formatMsg("warn.validator.resources.with.same.name", entryName));
         fps.put(internalName, fp);
         return;
     }
 
+    private void loadModuleDescriptor() {
+        ZipEntry je = jf.getEntry(MODULE_INFO);
+        if (je != null) {
+            try (InputStream jis = jf.getInputStream(je)) {
+                md = ModuleDescriptor.read(jis);
+                concealedPkgs = new HashSet<>(md.packages());
+                md.exports().stream().map(Exports::source).forEach(concealedPkgs::remove);
+                md.opens().stream().map(Opens::source).forEach(concealedPkgs::remove);
+                return;
+            } catch (Exception x) {
+                error(x.getMessage() + " : " + je.getName());
+                this.isValid = false;
+            }
+        }
+        md = null;
+        concealedPkgs = Collections.emptySet();
+    }
+
+    private static boolean isPlatformModule(String name) {
+        return name.startsWith("java.") || name.startsWith("jdk.");
+    }
+
+    /**
+     * Checks whether or not the given versioned module descriptor's attributes
+     * are valid when compared against the root module descriptor.
+     *
+     * A versioned module descriptor must be identical to the root module
+     * descriptor, with two exceptions:
+     *  - A versioned descriptor can have different non-public `requires`
+     *    clauses of platform ( `java.*` and `jdk.*` ) modules, and
+     *  - A versioned descriptor can have different `uses` clauses, even of
+     *    service types defined outside of the platform modules.
+     */
+    private void checkModuleDescriptor(JarEntry je) {
+        try (InputStream is = jf.getInputStream(je)) {
+            ModuleDescriptor root = this.md;
+            ModuleDescriptor md = null;
+            try {
+                md = ModuleDescriptor.read(is);
+            } catch (InvalidModuleDescriptorException x) {
+                error(x.getMessage());
+                isValid = false;
+                return;
+            }
+            if (root == null) {
+                this.md = md;
+            } else {
+                if (!root.name().equals(md.name())) {
+                    error(getMsg("error.versioned.info.name.notequal"));
+                    isValid = false;
+                }
+                if (!root.requires().equals(md.requires())) {
+                    Set<Requires> rootRequires = root.requires();
+                    for (Requires r : md.requires()) {
+                        if (rootRequires.contains(r))
+                            continue;
+                        if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) {
+                            error(getMsg("error.versioned.info.requires.transitive"));
+                            isValid = false;
+                        } else if (!isPlatformModule(r.name())) {
+                            error(getMsg("error.versioned.info.requires.added"));
+                            isValid = false;
+                        }
+                    }
+                    for (Requires r : rootRequires) {
+                        Set<Requires> mdRequires = md.requires();
+                        if (mdRequires.contains(r))
+                            continue;
+                        if (!isPlatformModule(r.name())) {
+                            error(getMsg("error.versioned.info.requires.dropped"));
+                            isValid = false;
+                        }
+                    }
+                }
+                if (!root.exports().equals(md.exports())) {
+                    error(getMsg("error.versioned.info.exports.notequal"));
+                    isValid = false;
+                }
+                if (!root.opens().equals(md.opens())) {
+                    error(getMsg("error.versioned.info.opens.notequal"));
+                    isValid = false;
+                }
+                if (!root.provides().equals(md.provides())) {
+                    error(getMsg("error.versioned.info.provides.notequal"));
+                    isValid = false;
+                }
+                if (!root.mainClass().equals(md.mainClass())) {
+                    error(formatMsg("error.validator.info.manclass.notequal", je.getName()));
+                    isValid = false;
+                }
+                if (!root.version().equals(md.version())) {
+                    error(formatMsg("error.validator.info.version.notequal", je.getName()));
+                    isValid = false;
+                }
+            }
+        } catch (IOException x) {
+            error(x.getMessage());
+            isValid = false;
+        }
+    }
+
     private boolean checkInternalName(String entryName, String basename, String internalName) {
         String className = className(basename);
         if (internalName.equals(className)) {
             return true;
         }
-        main.error(Main.formatMsg2("error.validator.names.mismatch",
+        error(formatMsg2("error.validator.names.mismatch",
                 entryName, internalName.replace("/", ".")));
         return false;
     }
@@ -231,7 +427,7 @@
             return true;
         }
         debug("top level class was not accepted");
-        main.error(Main.formatMsg("error.validator.isolated.nested.class", entryName));
+        error(formatMsg("error.validator.isolated.nested.class", entryName));
         return false;
     }
 
@@ -240,16 +436,24 @@
     }
 
     private boolean isConcealed(String internalName) {
-        if (main.concealedPackages.isEmpty()) {
+        if (concealedPkgs.isEmpty()) {
             return false;
         }
         int idx = internalName.lastIndexOf('/');
         String pkgName = idx != -1 ? internalName.substring(0, idx).replace('/', '.') : "";
-        return main.concealedPackages.contains(pkgName);
+        return concealedPkgs.contains(pkgName);
     }
 
     private void debug(String fmt, Object... args) {
         if (DEBUG) System.err.format(fmt, args);
     }
+
+    private void error(String msg) {
+        main.error(msg);
+    }
+
+    private void warn(String msg) {
+        main.warn(msg);
+    }
+
 }
-
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -66,23 +66,6 @@
         Unexpected module descriptor {0}
 error.module.descriptor.not.found=\
         Module descriptor not found
-error.versioned.info.without.root=\
-        module-info.class found in a versioned directory without module-info.class \
-        in the root
-error.versioned.info.name.notequal=\
-        module-info.class in a versioned directory contains incorrect name
-error.versioned.info.requires.transitive=\
-        module-info.class in a versioned directory contains additional "requires transitive"
-error.versioned.info.requires.added=\
-        module-info.class in a versioned directory contains additional "requires"
-error.versioned.info.requires.dropped=\
-        module-info.class in a versioned directory contains missing "requires"
-error.versioned.info.exports.notequal=\
-        module-info.class in a versioned directory contains different "exports"
-error.versioned.info.opens.notequal=\
-        module-info.class in a versioned directory contains different "opens"
-error.versioned.info.provides.notequal=\
-        module-info.class in a versioned directory contains different "provides"
 error.invalid.versioned.module.attribute=\
         Invalid module descriptor attribute {0}
 error.missing.provider=\
@@ -113,6 +96,24 @@
         entry: {0}, contains a class with different api from earlier version
 error.validator.names.mismatch=\
         entry: {0}, contains a class with internal name {1}, names do not match
+error.validator.info.name.notequal=\
+        module-info.class in a versioned directory contains incorrect name
+error.validator.info.requires.transitive=\
+        module-info.class in a versioned directory contains additional "requires transitive"
+error.validator.info.requires.added=\
+        module-info.class in a versioned directory contains additional "requires"
+error.validator.info.requires.dropped=\
+        module-info.class in a versioned directory contains missing "requires"
+error.validator.info.exports.notequal=\
+        module-info.class in a versioned directory contains different "exports"
+error.validator.info.opens.notequal=\
+        module-info.class in a versioned directory contains different "opens"
+error.validator.info.provides.notequal=\
+        module-info.class in a versioned directory contains different "provides"
+error.validator.info.version.notequal=\
+        {0}: module-info.class in a versioned directory contains different "version"
+error.validator.info.manclass.notequal=\
+        {0}: module-info.class in a versioned directory contains different "main-class"
 warn.validator.identical.entry=\
         Warning: entry {0} contains a class that\n\
         is identical to an entry already in the jar
@@ -122,6 +123,8 @@
         Warning: entry {0} is a public class\n\
         in a concealed package, placing this jar on the class path will result\n\
         in incompatible public interfaces
+warn.release.unexpected.versioned.entry=\
+        unexpected versioned entry {0}
 out.added.manifest=\
         added manifest
 out.added.module-info=\
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=--module-version oder --hash-modules ohne module-info.class
 error.unexpected.module-info=Unerwarteter Moduldeskriptor {0}
 error.module.descriptor.not.found=Moduldeskriptor nicht gefunden
-error.versioned.info.without.root=module-info.class in einem versionierten Verzeichnis gefunden, in der Root ist module-info.class jedoch nicht vorhanden
-error.versioned.info.name.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt falschen Namen
-error.versioned.info.requires.public=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires public"
-error.versioned.info.requires.added=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires"
-error.versioned.info.requires.dropped=module-info.class in einem versionierten Verzeichnis enth\u00E4lt fehlenden "requires"
-error.versioned.info.exports.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "exports"
-error.versioned.info.provides.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "provides"
+error.validator.info.without.root=module-info.class in einem versionierten Verzeichnis gefunden, in der Root ist module-info.class jedoch nicht vorhanden
+error.validator.info.name.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt falschen Namen
+error.validator.info.requires.public=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires public"
+error.validator.info.requires.added=module-info.class in einem versionierten Verzeichnis enth\u00E4lt zus\u00E4tzlichen "requires"
+error.validator.info.requires.dropped=module-info.class in einem versionierten Verzeichnis enth\u00E4lt fehlenden "requires"
+error.validator.info.exports.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "exports"
+error.validator.info.provides.notequal=module-info.class in einem versionierten Verzeichnis enth\u00E4lt unterschiedliche "provides"
 error.invalid.versioned.module.attribute=Ung\u00FCltiges Moduldeskriptorattribut {0}
 error.missing.provider=Serviceprovider nicht gefunden: {0}
 error.release.value.notnumber=Release {0} nicht g\u00FCltig
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_es.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_es.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=Uno de --module-version o -hash-modules sin module-info.class
 error.unexpected.module-info=Descriptor de m\u00F3dulo inesperado {0}
 error.module.descriptor.not.found=No se ha encontrado el descriptor de m\u00F3dulo
-error.versioned.info.without.root=Se ha encontrado module-info.class en un directorio con versi\u00F3n sin module-info.class en la ra\u00EDz
-error.versioned.info.name.notequal=module-info.class en un directorio con versi\u00F3n contiene un nombre incorrecto
-error.versioned.info.requires.public=module-info.class en un directorio con versiones contiene "requires public" adicionales
-error.versioned.info.requires.added=module-info.class en un directorio con versi\u00F3n contiene "requires" adicionales
-error.versioned.info.requires.dropped=module-info.class en un directorio con versiones contiene "requires" que faltan
-error.versioned.info.exports.notequal=module-info.class en un directorio con versiones contiene "exports" diferentes
-error.versioned.info.provides.notequal=module-info.class en un directorio con versiones contiene "provides" diferentes
+error.validator.info.without.root=Se ha encontrado module-info.class en un directorio con versi\u00F3n sin module-info.class en la ra\u00EDz
+error.validator.info.name.notequal=module-info.class en un directorio con versi\u00F3n contiene un nombre incorrecto
+error.validator.info.requires.public=module-info.class en un directorio con versiones contiene "requires public" adicionales
+error.validator.info.requires.added=module-info.class en un directorio con versi\u00F3n contiene "requires" adicionales
+error.validator.info.requires.dropped=module-info.class en un directorio con versiones contiene "requires" que faltan
+error.validator.info.exports.notequal=module-info.class en un directorio con versiones contiene "exports" diferentes
+error.validator.info.provides.notequal=module-info.class en un directorio con versiones contiene "provides" diferentes
 error.invalid.versioned.module.attribute=Atributo de descriptor de m\u00F3dulo no v\u00E1lido {0}
 error.missing.provider=No se ha encontrado el proveedor de servicios: {0}
 error.release.value.notnumber=versi\u00F3n {0} no v\u00E1lida
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_fr.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_fr.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=Une des options --module-version ou --hash-modules sans module-info.class
 error.unexpected.module-info=Descripteur de module {0} inattendu
 error.module.descriptor.not.found=Descripteur de module introuvable
-error.versioned.info.without.root=module-info.class a \u00E9t\u00E9 d\u00E9tect\u00E9 dans un r\u00E9pertoire avec num\u00E9ro de version sans module-info.class dans la racine
-error.versioned.info.name.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient un nom incorrect
-error.versioned.info.requires.public=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires public" suppl\u00E9mentaires
-error.versioned.info.requires.added=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" suppl\u00E9mentaires
-error.versioned.info.requires.dropped=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" manquants
-error.versioned.info.exports.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "exports" diff\u00E9rents
-error.versioned.info.provides.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "provides" diff\u00E9rents
+error.validator.info.without.root=module-info.class a \u00E9t\u00E9 d\u00E9tect\u00E9 dans un r\u00E9pertoire avec num\u00E9ro de version sans module-info.class dans la racine
+error.validator.info.name.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient un nom incorrect
+error.validator.info.requires.public=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires public" suppl\u00E9mentaires
+error.validator.info.requires.added=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" suppl\u00E9mentaires
+error.validator.info.requires.dropped=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "requires" manquants
+error.validator.info.exports.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "exports" diff\u00E9rents
+error.validator.info.provides.notequal=module-info.class dans un r\u00E9pertoire avec num\u00E9ro de version contient des mots-cl\u00E9s "provides" diff\u00E9rents
 error.invalid.versioned.module.attribute=Attribut de descripteur de module non valide {0}
 error.missing.provider=Fournisseur de services introuvable : {0}
 error.release.value.notnumber=version {0} non valide
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_it.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_it.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=Una delle opzioni --module-version o --hash-modules non contiene module-info.class
 error.unexpected.module-info=Descrittore di modulo {0} imprevisto
 error.module.descriptor.not.found=Descrittore di modulo non trovato
-error.versioned.info.without.root=module-info.class trovato in una directory con controllo delle versioni senza module-info.class nella radice
-error.versioned.info.name.notequal=module-info.class in una directory con controllo delle versioni contiene un nome errato
-error.versioned.info.requires.public=module-info.class in una directory con controllo delle versioni contiene valori "requires public" aggiuntivi
-error.versioned.info.requires.added=module-info.class in una directory con controllo delle versioni contiene valori "requires" aggiuntivi
-error.versioned.info.requires.dropped=module-info.class in una directory con controllo delle versioni contiene valori "requires" mancanti
-error.versioned.info.exports.notequal=module-info.class in una directory con controllo delle versioni contiene "exports" differenti
-error.versioned.info.provides.notequal=module-info.class in una directory con controllo delle versioni contiene valori "provides" differenti
+error.validator.info.without.root=module-info.class trovato in una directory con controllo delle versioni senza module-info.class nella radice
+error.validator.info.name.notequal=module-info.class in una directory con controllo delle versioni contiene un nome errato
+error.validator.info.requires.public=module-info.class in una directory con controllo delle versioni contiene valori "requires public" aggiuntivi
+error.validator.info.requires.added=module-info.class in una directory con controllo delle versioni contiene valori "requires" aggiuntivi
+error.validator.info.requires.dropped=module-info.class in una directory con controllo delle versioni contiene valori "requires" mancanti
+error.validator.info.exports.notequal=module-info.class in una directory con controllo delle versioni contiene "exports" differenti
+error.validator.info.provides.notequal=module-info.class in una directory con controllo delle versioni contiene valori "provides" differenti
 error.invalid.versioned.module.attribute=Attributo descrittore del modulo {0} non valido.
 error.missing.provider=Provider di servizi non trovato: {0}
 error.release.value.notnumber=release {0} non valida
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=--module-version\u307E\u305F\u306F--hash-modules\u306E\u3044\u305A\u308C\u304B\u3067module-info.class\u304C\u3042\u308A\u307E\u305B\u3093
 error.unexpected.module-info=\u4E88\u671F\u3057\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF{0}
 error.module.descriptor.not.found=\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
-error.versioned.info.without.root=module-info.class\u304C\u3001\u30EB\u30FC\u30C8\u306Bmodule-info.class\u306E\u306A\u3044\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u898B\u3064\u304B\u308A\u307E\u3057\u305F
-error.versioned.info.name.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B63\u3057\u304F\u306A\u3044\u540D\u524D\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.requires.public=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires public"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.requires.added=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.requires.dropped=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B20\u843D\u3057\u3066\u3044\u308B"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.exports.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"exports"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
-error.versioned.info.provides.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"provides"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.without.root=module-info.class\u304C\u3001\u30EB\u30FC\u30C8\u306Bmodule-info.class\u306E\u306A\u3044\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u898B\u3064\u304B\u308A\u307E\u3057\u305F
+error.validator.info.name.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B63\u3057\u304F\u306A\u3044\u540D\u524D\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.requires.public=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires public"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.requires.added=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u8FFD\u52A0\u306E"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.requires.dropped=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u6B20\u843D\u3057\u3066\u3044\u308B"requires"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.exports.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"exports"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
+error.validator.info.provides.notequal=\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306Emodule-info.class\u306B\u7570\u306A\u308B"provides"\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059
 error.invalid.versioned.module.attribute=\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF\u5C5E\u6027{0}\u304C\u7121\u52B9\u3067\u3059
 error.missing.provider=\u30B5\u30FC\u30D3\u30B9\u30FB\u30D7\u30ED\u30D0\u30A4\u30C0\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0}
 error.release.value.notnumber=\u30EA\u30EA\u30FC\u30B9{0}\u306F\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ko.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ko.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=module-info.class \uC5C6\uC774 --module-version \uB610\uB294 --hash-modules \uC911 \uD558\uB098
 error.unexpected.module-info=\uC608\uC0C1\uCE58 \uC54A\uC740 \uBAA8\uB4C8 \uAE30\uC220\uC790 {0}
 error.module.descriptor.not.found=\uBAA8\uB4C8 \uAE30\uC220\uC790\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C
-error.versioned.info.without.root=\uB8E8\uD2B8\uC5D0\uC11C module-info.class \uC5C6\uC774 \uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C module-info.class\uAC00 \uBC1C\uACAC\uB428
-error.versioned.info.name.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uC798\uBABB\uB41C \uC774\uB984\uC774 \uD3EC\uD568\uB428
-error.versioned.info.requires.public=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires public" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.requires.added=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.requires.dropped=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB204\uB77D\uB41C "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.exports.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "exports" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
-error.versioned.info.provides.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "provides" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.without.root=\uB8E8\uD2B8\uC5D0\uC11C module-info.class \uC5C6\uC774 \uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C module-info.class\uAC00 \uBC1C\uACAC\uB428
+error.validator.info.name.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uC798\uBABB\uB41C \uC774\uB984\uC774 \uD3EC\uD568\uB428
+error.validator.info.requires.public=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires public" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.requires.added=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uCD94\uAC00 "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.requires.dropped=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB204\uB77D\uB41C "requires" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.exports.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "exports" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
+error.validator.info.provides.notequal=\uBC84\uC804 \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uC758 module-info.class\uC5D0 \uB2E4\uB978 "provides" \uD56D\uBAA9\uC774 \uD3EC\uD568\uB428
 error.invalid.versioned.module.attribute=\uBD80\uC801\uD569\uD55C \uBAA8\uB4C8 \uAE30\uC220\uC790 \uC18D\uC131 {0}
 error.missing.provider=\uC11C\uBE44\uC2A4 \uC81C\uACF5\uC790\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC74C: {0}
 error.release.value.notnumber=\uB9B4\uB9AC\uC2A4 {0}\uC774(\uAC00) \uBD80\uC801\uD569\uD568
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_pt_BR.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_pt_BR.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=Um dentre --module-version ou --hash-modules est\u00E1 sem module-info.class
 error.unexpected.module-info=Descritor de m\u00F3dulo inesperado {0}
 error.module.descriptor.not.found=Descritor de m\u00F3dulo n\u00E3o encontrado
-error.versioned.info.without.root=module-info.class encontrado em um diret\u00F3rio com controle de vers\u00E3o sem module-info.class na raiz
-error.versioned.info.name.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m nome incorreto
-error.versioned.info.requires.public=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires public" adicional
-error.versioned.info.requires.added=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires" adicional
-error.versioned.info.requires.dropped=module-info.class em um diret\u00F3rio com controle de vers\u00E3o falta "requires"
-error.versioned.info.exports.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "exports" diferente
-error.versioned.info.provides.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "provides" diferente
+error.validator.info.without.root=module-info.class encontrado em um diret\u00F3rio com controle de vers\u00E3o sem module-info.class na raiz
+error.validator.info.name.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m nome incorreto
+error.validator.info.requires.public=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires public" adicional
+error.validator.info.requires.added=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "requires" adicional
+error.validator.info.requires.dropped=module-info.class em um diret\u00F3rio com controle de vers\u00E3o falta "requires"
+error.validator.info.exports.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "exports" diferente
+error.validator.info.provides.notequal=module-info.class em um diret\u00F3rio com controle de vers\u00E3o cont\u00E9m "provides" diferente
 error.invalid.versioned.module.attribute=Atributo {0} de descritor de m\u00F3dulo inv\u00E1lido
 error.missing.provider=Prestador de servi\u00E7os  n\u00E3o encontrado: {0}
 error.release.value.notnumber=release {0} n\u00E3o v\u00E1lida
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_sv.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_sv.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=--module-version eller --hash-modules utan module-info.class
 error.unexpected.module-info=Ov\u00E4ntad moduldeskriptor, {0}
 error.module.descriptor.not.found=Moduldeskriptorn hittades inte
-error.versioned.info.without.root=module-info.class hittades i en versionshanterad katalog utan module-info.class i roten
-error.versioned.info.name.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller ett felaktigt namn
-error.versioned.info.requires.public=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires public"
-error.versioned.info.requires.added=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires"
-error.versioned.info.requires.dropped=module-info.class i en versionshanterad katalog inneh\u00E5ller saknade "requires"
-error.versioned.info.exports.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "exports"
-error.versioned.info.provides.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "provides"
+error.validator.info.without.root=module-info.class hittades i en versionshanterad katalog utan module-info.class i roten
+error.validator.info.name.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller ett felaktigt namn
+error.validator.info.requires.public=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires public"
+error.validator.info.requires.added=module-info.class i en versionshanterad katalog inneh\u00E5ller fler "requires"
+error.validator.info.requires.dropped=module-info.class i en versionshanterad katalog inneh\u00E5ller saknade "requires"
+error.validator.info.exports.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "exports"
+error.validator.info.provides.notequal=module-info.class i en versionshanterad katalog inneh\u00E5ller olika "provides"
 error.invalid.versioned.module.attribute=Ogiltigt attribut f\u00F6r moduldeskriptor, {0}
 error.missing.provider=Tj\u00E4nsteleverant\u00F6ren hittades inte: {0}
 error.release.value.notnumber=utg\u00E5va {0} \u00E4r inte giltig
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=--module-version \u6216 --hash-modules \u4E4B\u4E00\u6CA1\u6709 module-info.class
 error.unexpected.module-info=\u610F\u5916\u7684\u6A21\u5757\u63CF\u8FF0\u7B26 {0}
 error.module.descriptor.not.found=\u627E\u4E0D\u5230\u6A21\u5757\u63CF\u8FF0\u7B26
-error.versioned.info.without.root=\u5728\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u627E\u5230\u4E86 module-info.class, \u4F46\u6839\u4E2D\u6CA1\u6709 module-info.class
-error.versioned.info.name.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u786E\u7684\u540D\u79F0
-error.versioned.info.requires.public=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires public"
-error.versioned.info.requires.added=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires"
-error.versioned.info.requires.dropped=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u7F3A\u5C11\u7684 "requires"
-error.versioned.info.exports.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
-error.versioned.info.provides.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
+error.validator.info.without.root=\u5728\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u627E\u5230\u4E86 module-info.class, \u4F46\u6839\u4E2D\u6CA1\u6709 module-info.class
+error.validator.info.name.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u786E\u7684\u540D\u79F0
+error.validator.info.requires.public=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires public"
+error.validator.info.requires.added=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u989D\u5916\u7684 "requires"
+error.validator.info.requires.dropped=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u7F3A\u5C11\u7684 "requires"
+error.validator.info.exports.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
+error.validator.info.provides.notequal=\u7248\u672C\u5316\u76EE\u5F55\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
 error.invalid.versioned.module.attribute=\u65E0\u6548\u7684\u6A21\u5757\u63CF\u8FF0\u7B26\u5C5E\u6027 {0}
 error.missing.provider=\u672A\u627E\u5230\u670D\u52A1\u63D0\u4F9B\u65B9: {0}
 error.release.value.notnumber=\u53D1\u884C\u7248 {0} \u65E0\u6548
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_TW.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_TW.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -42,13 +42,13 @@
 error.module.options.without.info=--module-version \u6216 --hash-modules \u5176\u4E2D\u4E00\u500B\u6C92\u6709 module-info.class
 error.unexpected.module-info=\u672A\u9810\u671F\u7684\u6A21\u7D44\u63CF\u8FF0\u5340 {0}
 error.module.descriptor.not.found=\u627E\u4E0D\u5230\u6A21\u7D44\u63CF\u8FF0\u5340
-error.versioned.info.without.root=\u5728\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u767C\u73FE module-info.class\uFF0C\u4F46\u662F\u6839\u4E2D\u6C92\u6709 module-info.class
-error.versioned.info.name.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u78BA\u7684\u540D\u7A31
-error.versioned.info.requires.public=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires public"
-error.versioned.info.requires.added=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires"
-error.versioned.info.requires.dropped=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u907A\u6F0F\u7684 "requires"
-error.versioned.info.exports.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
-error.versioned.info.provides.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
+error.validator.info.without.root=\u5728\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u767C\u73FE module-info.class\uFF0C\u4F46\u662F\u6839\u4E2D\u6C92\u6709 module-info.class
+error.validator.info.name.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u6B63\u78BA\u7684\u540D\u7A31
+error.validator.info.requires.public=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires public"
+error.validator.info.requires.added=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u984D\u5916\u7684 "requires"
+error.validator.info.requires.dropped=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u907A\u6F0F\u7684 "requires"
+error.validator.info.exports.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "exports"
+error.validator.info.provides.notequal=\u5DF2\u555F\u52D5\u591A\u7248\u672C\u529F\u80FD\u76EE\u9304\u4E2D\u7684 module-info.class \u5305\u542B\u4E0D\u540C\u7684 "provides"
 error.invalid.versioned.module.attribute=\u6A21\u7D44\u63CF\u8FF0\u5340\u5C6C\u6027 {0} \u7121\u6548
 error.missing.provider=\u627E\u4E0D\u5230\u670D\u52D9\u63D0\u4F9B\u8005: {0}
 error.release.value.notnumber=\u7248\u672C {0} \u7121\u6548
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,13 +58,10 @@
 import java.nio.file.StandardCopyOption;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.text.MessageFormat;
-import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Deque;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -101,6 +98,7 @@
 import jdk.internal.joptsimple.ValueConverter;
 import jdk.internal.loader.ResourceHelper;
 import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleHashesBuilder;
 import jdk.internal.module.ModuleInfo;
 import jdk.internal.module.ModuleInfoExtender;
 import jdk.internal.module.ModulePath;
@@ -286,7 +284,27 @@
     }
 
     private boolean hashModules() {
-        return new Hasher(options.moduleFinder).run();
+        if (options.dryrun) {
+            out.println("Dry run:");
+        }
+
+        Hasher hasher = new Hasher(options.moduleFinder);
+        hasher.computeHashes().forEach((mn, hashes) -> {
+            if (options.dryrun) {
+                out.format("%s%n", mn);
+                hashes.names().stream()
+                    .sorted()
+                    .forEach(name -> out.format("  hashes %s %s %s%n",
+                        name, hashes.algorithm(), toHex(hashes.hashFor(name))));
+            } else {
+                try {
+                    hasher.updateModuleInfo(mn, hashes);
+                } catch (IOException ex) {
+                    throw new UncheckedIOException(ex);
+                }
+            }
+        });
+        return true;
     }
 
     private boolean describe() throws IOException {
@@ -377,7 +395,7 @@
         // create jmod with temporary name to avoid it being examined
         // when scanning the module path
         Path target = options.jmodFile;
-        Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
+        Path tempTarget = Files.createTempFile(target.getFileName().toString(), ".tmp");
         try {
             try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) {
                 jmod.write(jos);
@@ -411,7 +429,6 @@
         final String osArch = options.osArch;
         final String osVersion = options.osVersion;
         final List<PathMatcher> excludes = options.excludes;
-        final Hasher hasher = hasher();
         final ModuleResolution moduleResolution = options.moduleResolution;
 
         JmodFileWriter() { }
@@ -514,8 +531,17 @@
                 if (moduleVersion != null)
                     extender.version(moduleVersion);
 
-                if (hasher != null) {
-                    ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name());
+                // --hash-modules
+                if (options.modulesToHash != null) {
+                    // To compute hashes, it creates a Configuration to resolve
+                    // a module graph.  The post-resolution check requires
+                    // the packages in ModuleDescriptor be available for validation.
+                    ModuleDescriptor md;
+                    try (InputStream is = miSupplier.get()) {
+                        md = ModuleDescriptor.read(is, () -> packages);
+                    }
+
+                    ModuleHashes moduleHashes = computeHashes(md);
                     if (moduleHashes != null) {
                         extender.hashes(moduleHashes);
                     } else {
@@ -557,50 +583,34 @@
          * The jmod file is being created and does not exist in the
          * given modulepath.
          */
-        private Hasher hasher() {
-            if (options.modulesToHash == null)
-                return null;
-
-            try {
-                Supplier<InputStream> miSupplier = newModuleInfoSupplier();
-                if (miSupplier == null) {
-                    throw new IOException(MODULE_INFO + " not found");
+        private ModuleHashes computeHashes(ModuleDescriptor descriptor) {
+            String mn = descriptor.name();
+            URI uri = options.jmodFile.toUri();
+            ModuleReference mref = new ModuleReference(descriptor, uri) {
+                @Override
+                public ModuleReader open() {
+                    throw new UnsupportedOperationException("opening " + mn);
                 }
+            };
 
-                ModuleDescriptor descriptor;
-                try (InputStream in = miSupplier.get()) {
-                    descriptor = ModuleDescriptor.read(in);
-                }
-
-                URI uri = options.jmodFile.toUri();
-                ModuleReference mref = new ModuleReference(descriptor, uri) {
+            // compose a module finder with the module path and also
+            // a module finder that can find the jmod file being created
+            ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
+                new ModuleFinder() {
                     @Override
-                    public ModuleReader open() {
-                        throw new UnsupportedOperationException();
+                    public Optional<ModuleReference> find(String name) {
+                        if (descriptor.name().equals(name))
+                            return Optional.of(mref);
+                        else return Optional.empty();
                     }
-                };
 
-                // compose a module finder with the module path and also
-                // a module finder that can find the jmod file being created
-                ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
-                    new ModuleFinder() {
-                        @Override
-                        public Optional<ModuleReference> find(String name) {
-                            if (descriptor.name().equals(name))
-                                return Optional.of(mref);
-                            else return Optional.empty();
-                        }
+                    @Override
+                    public Set<ModuleReference> findAll() {
+                        return Collections.singleton(mref);
+                    }
+                });
 
-                        @Override
-                        public Set<ModuleReference> findAll() {
-                            return Collections.singleton(mref);
-                        }
-                    });
-
-                return new Hasher(finder);
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
+            return new Hasher(mn, finder).computeHashes().get(mn);
         }
 
         /**
@@ -789,192 +799,93 @@
      * Compute and record hashes
      */
     private class Hasher {
-        final ModuleFinder moduleFinder;
-        final Map<String, Path> moduleNameToPath;
+        final Configuration configuration;
+        final ModuleHashesBuilder hashesBuilder;
         final Set<String> modules;
-        final Configuration configuration;
-        final boolean dryrun = options.dryrun;
+        final String moduleName;  // a specific module to record hashes, if set
+
+        /**
+         * This constructor is for jmod hash command.
+         *
+         * This Hasher will determine which modules to record hashes, i.e.
+         * the module in a subgraph of modules to be hashed and that
+         * has no outgoing edges.  It will record in each of these modules,
+         * say `M`, with the the hashes of modules that depend upon M
+         * directly or indirectly matching the specified --hash-modules pattern.
+         */
         Hasher(ModuleFinder finder) {
-            this.moduleFinder = finder;
+            this(null, finder);
+        }
+
+        /**
+         * Constructs a Hasher to compute hashes.
+         *
+         * If a module name `M` is specified, it will compute the hashes of
+         * modules that depend upon M directly or indirectly matching the
+         * specified --hash-modules pattern and record in the ModuleHashes
+         * attribute in M's module-info.class.
+         *
+         * @param name    name of the module to record hashes
+         * @param finder  module finder for the specified --module-path
+         */
+        Hasher(String name, ModuleFinder finder) {
             // Determine the modules that matches the pattern {@code modulesToHash}
-            this.modules = moduleFinder.findAll().stream()
+            Set<String> roots = finder.findAll().stream()
                 .map(mref -> mref.descriptor().name())
                 .filter(mn -> options.modulesToHash.matcher(mn).find())
                 .collect(Collectors.toSet());
 
-            // a map from a module name to Path of the packaged module
-            this.moduleNameToPath = moduleFinder.findAll().stream()
-                .map(mref -> mref.descriptor().name())
-                .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
-
+            // use system module path unless it creates a JMOD file for
+            // a module that is present in the system image e.g. upgradeable
+            // module
+            ModuleFinder system;
+            if (name != null && ModuleFinder.ofSystem().find(name).isPresent()) {
+                system = ModuleFinder.of();
+            } else {
+                system = ModuleFinder.ofSystem();
+            }
             // get a resolved module graph
             Configuration config = null;
             try {
-                config = Configuration.empty()
-                    .resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules);
+                config = Configuration.empty().resolveRequires(system, finder, roots);
             } catch (ResolutionException e) {
-                warning("warn.module.resolution.fail", e.getMessage());
+                throw new CommandException("err.module.resolution.fail", e.getMessage());
             }
+
+            this.moduleName = name;
             this.configuration = config;
+
+            // filter modules resolved from the system module finder
+            this.modules = config.modules().stream()
+                .map(ResolvedModule::name)
+                .filter(mn -> roots.contains(mn) && !system.find(mn).isPresent())
+                .collect(Collectors.toSet());
+
+            this.hashesBuilder = new ModuleHashesBuilder(config, modules);
         }
 
         /**
-         * This method is for jmod hash command.
+         * Returns a map of a module M to record hashes of the modules
+         * that depend upon M directly or indirectly.
          *
-         * Identify the base modules in the module graph, i.e. no outgoing edge
-         * to any of the modules to be hashed.
+         * For jmod hash command, the returned map contains one entry
+         * for each module M that has no outgoing edges to any of the
+         * modules matching the specified --hash-modules pattern.
          *
-         * For each base module M, compute the hashes of all modules that depend
-         * upon M directly or indirectly.  Then update M's module-info.class
-         * to record the hashes.
+         * Each entry represents a leaf node in a connected subgraph containing
+         * M and other candidate modules from the module graph where M's outgoing
+         * edges to any module other than the ones matching the specified
+         * --hash-modules pattern are excluded.
          */
-        boolean run() {
-            if (configuration == null)
-                return false;
-
-            // transposed graph containing the the packaged modules and
-            // its transitive dependences matching --hash-modules
-            Map<String, Set<String>> graph = new HashMap<>();
-            for (String root : modules) {
-                Deque<String> deque = new ArrayDeque<>();
-                deque.add(root);
-                Set<String> visited = new HashSet<>();
-                while (!deque.isEmpty()) {
-                    String mn = deque.pop();
-                    if (!visited.contains(mn)) {
-                        visited.add(mn);
-
-                        if (modules.contains(mn))
-                            graph.computeIfAbsent(mn, _k -> new HashSet<>());
-
-                        ResolvedModule resolvedModule = configuration.findModule(mn).get();
-                        for (ResolvedModule dm : resolvedModule.reads()) {
-                            String name = dm.name();
-                            if (!visited.contains(name)) {
-                                deque.push(name);
-                            }
-
-                            // reverse edge
-                            if (modules.contains(name) && modules.contains(mn)) {
-                                graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn);
-                            }
-                        }
-                    }
-                }
-            }
-
-            if (dryrun)
-                out.println("Dry run:");
-
-            // each node in a transposed graph is a matching packaged module
-            // in which the hash of the modules that depend upon it is recorded
-            graph.entrySet().stream()
-                .filter(e -> !e.getValue().isEmpty())
-                .forEach(e -> {
-                    String mn = e.getKey();
-                    Map<String, Path> modulesForHash = e.getValue().stream()
-                            .collect(Collectors.toMap(Function.identity(),
-                                                      moduleNameToPath::get));
-                    ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256");
-                    if (dryrun) {
-                        out.format("%s%n", mn);
-                        hashes.names().stream()
-                              .sorted()
-                              .forEach(name -> out.format("  hashes %s %s %s%n",
-                                  name, hashes.algorithm(), hashes.hashFor(name)));
-                    } else {
-                        try {
-                            updateModuleInfo(mn, hashes);
-                        } catch (IOException ex) {
-                            throw new UncheckedIOException(ex);
-                        }
-                    }
-                });
-            return true;
-        }
-
-        /**
-         * Compute hashes of the specified module.
-         *
-         * It records the hashing modules that depend upon the specified
-         * module directly or indirectly.
-         */
-        ModuleHashes computeHashes(String name) {
-            if (configuration == null)
+        Map<String, ModuleHashes> computeHashes() {
+            if (hashesBuilder == null)
                 return null;
 
-            // the transposed graph includes all modules in the resolved graph
-            Map<String, Set<String>> graph = transpose();
-
-            // find the modules that transitively depend upon the specified name
-            Deque<String> deque = new ArrayDeque<>();
-            deque.add(name);
-            Set<String> mods = visitNodes(graph, deque);
-
-            // filter modules matching the pattern specified --hash-modules
-            // as well as itself as the jmod file is being generated
-            Map<String, Path> modulesForHash = mods.stream()
-                .filter(mn -> !mn.equals(name) && modules.contains(mn))
-                .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
-
-            if (modulesForHash.isEmpty())
-                return null;
-
-           return ModuleHashes.generate(modulesForHash, "SHA-256");
-        }
-
-        /**
-         * Returns all nodes traversed from the given roots.
-         */
-        private Set<String> visitNodes(Map<String, Set<String>> graph,
-                                       Deque<String> roots) {
-            Set<String> visited = new HashSet<>();
-            while (!roots.isEmpty()) {
-                String mn = roots.pop();
-                if (!visited.contains(mn)) {
-                    visited.add(mn);
-                    // the given roots may not be part of the graph
-                    if (graph.containsKey(mn)) {
-                        for (String dm : graph.get(mn)) {
-                            if (!visited.contains(dm)) {
-                                roots.push(dm);
-                            }
-                        }
-                    }
-                }
+            if (moduleName != null) {
+                return hashesBuilder.computeHashes(Set.of(moduleName));
+            } else {
+                return hashesBuilder.computeHashes(modules);
             }
-            return visited;
-        }
-
-        /**
-         * Returns a transposed graph from the resolved module graph.
-         */
-        private Map<String, Set<String>> transpose() {
-            Map<String, Set<String>> transposedGraph = new HashMap<>();
-            Deque<String> deque = new ArrayDeque<>(modules);
-
-            Set<String> visited = new HashSet<>();
-            while (!deque.isEmpty()) {
-                String mn = deque.pop();
-                if (!visited.contains(mn)) {
-                    visited.add(mn);
-
-                    transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
-
-                    ResolvedModule resolvedModule = configuration.findModule(mn).get();
-                    for (ResolvedModule dm : resolvedModule.reads()) {
-                        String name = dm.name();
-                        if (!visited.contains(name)) {
-                            deque.push(name);
-                        }
-
-                        // reverse edge
-                        transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
-                                .add(mn);
-                    }
-                }
-            }
-            return transposedGraph;
         }
 
         /**
@@ -993,11 +904,11 @@
             extender.write(out);
         }
 
-        private void updateModuleInfo(String name, ModuleHashes moduleHashes)
+        void updateModuleInfo(String name, ModuleHashes moduleHashes)
             throws IOException
         {
-            Path target = moduleNameToPath.get(name);
-            Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp");
+            Path target = moduleToPath(name);
+            Path tempTarget = Files.createTempFile(target.getFileName().toString(), ".tmp");
             try {
                 if (target.getFileName().toString().endsWith(".jmod")) {
                     updateJmodFile(target, tempTarget, moduleHashes);
@@ -1075,10 +986,10 @@
         }
 
         private Path moduleToPath(String name) {
-            ModuleReference mref = moduleFinder.find(name).orElseThrow(
+            ResolvedModule rm = configuration.findModule(name).orElseThrow(
                 () -> new InternalError("Selected module " + name + " not on module path"));
 
-            URI uri = mref.location().get();
+            URI uri = rm.reference().location().get();
             Path path = Paths.get(uri);
             String fn = path.getFileName().toString();
             if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
@@ -1088,34 +999,58 @@
         }
     }
 
-    static class ClassPathConverter implements ValueConverter<Path> {
-        static final ValueConverter<Path> INSTANCE = new ClassPathConverter();
+    /**
+     * An abstract converter that given a string representing a list of paths,
+     * separated by the File.pathSeparator, returns a List of java.nio.Path's.
+     * Specific subclasses should do whatever validation is required on the
+     * individual path elements, if any.
+     */
+    static abstract class AbstractPathConverter implements ValueConverter<List<Path>> {
+        @Override
+        public List<Path> convert(String value) {
+            List<Path> paths = new ArrayList<>();
+            String[] pathElements = value.split(File.pathSeparator);
+            for (String pathElement : pathElements) {
+                paths.add(toPath(pathElement));
+            }
+            return paths;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Class<List<Path>> valueType() {
+            return (Class<List<Path>>)(Object)List.class;
+        }
+
+        @Override public String valuePattern() { return "path"; }
+
+        abstract Path toPath(String path);
+    }
+
+    static class ClassPathConverter extends AbstractPathConverter {
+        static final ValueConverter<List<Path>> INSTANCE = new ClassPathConverter();
 
         @Override
-        public Path convert(String value) {
+        public Path toPath(String value) {
             try {
                 Path path = CWD.resolve(value);
                 if (Files.notExists(path))
                     throw new CommandException("err.path.not.found", path);
-                if (! (Files.isDirectory(path) ||
-                       (Files.isRegularFile(path) && path.toString().endsWith(".jar"))))
+                if (!(Files.isDirectory(path) ||
+                        (Files.isRegularFile(path) && path.toString().endsWith(".jar"))))
                     throw new CommandException("err.invalid.class.path.entry", path);
                 return path;
             } catch (InvalidPathException x) {
                 throw new CommandException("err.path.not.valid", value);
             }
         }
-
-        @Override  public Class<Path> valueType() { return Path.class; }
-
-        @Override  public String valuePattern() { return "path"; }
     }
 
-    static class DirPathConverter implements ValueConverter<Path> {
-        static final ValueConverter<Path> INSTANCE = new DirPathConverter();
+    static class DirPathConverter extends AbstractPathConverter {
+        static final ValueConverter<List<Path>> INSTANCE = new DirPathConverter();
 
         @Override
-        public Path convert(String value) {
+        public Path toPath(String value) {
             try {
                 Path path = CWD.resolve(value);
                 if (Files.notExists(path))
@@ -1127,10 +1062,6 @@
                 throw new CommandException("err.path.not.valid", value);
             }
         }
-
-        @Override  public Class<Path> valueType() { return Path.class; }
-
-        @Override  public String valuePattern() { return "path"; }
     }
 
     static class ExtractDirPathConverter implements ValueConverter<Path> {
@@ -1142,12 +1073,6 @@
                 if (Files.exists(path)) {
                     if (!Files.isDirectory(path))
                         throw new CommandException("err.cannot.create.dir", path);
-                } else {
-                    try {
-                        Files.createDirectories(path);
-                    } catch (IOException ioe) {
-                        throw new CommandException("err.cannot.create.dir", path);
-                    }
                 }
                 return path;
             } catch (InvalidPathException x) {
@@ -1316,22 +1241,19 @@
         options = new Options();
         parser.formatHelpWith(new JmodHelpFormatter(options));
 
-        OptionSpec<Path> classPath
+        OptionSpec<List<Path>> classPath
                 = parser.accepts("class-path", getMessage("main.opt.class-path"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(ClassPathConverter.INSTANCE);
 
-        OptionSpec<Path> cmds
+        OptionSpec<List<Path>> cmds
                 = parser.accepts("cmds", getMessage("main.opt.cmds"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
-        OptionSpec<Path> config
+        OptionSpec<List<Path>> config
                 = parser.accepts("config", getMessage("main.opt.config"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
         OptionSpec<Path> dir
@@ -1359,22 +1281,19 @@
         OptionSpec<Void> helpExtra
                 = parser.accepts("help-extra", getMessage("main.opt.help-extra"));
 
-        OptionSpec<Path> headerFiles
+        OptionSpec<List<Path>> headerFiles
                 = parser.accepts("header-files", getMessage("main.opt.header-files"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
-        OptionSpec<Path> libs
+        OptionSpec<List<Path>> libs
                 = parser.accepts("libs", getMessage("main.opt.libs"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
-        OptionSpec<Path> legalNotices
+        OptionSpec<List<Path>> legalNotices
                 = parser.accepts("legal-notices", getMessage("main.opt.legal-notices"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
 
@@ -1383,17 +1302,15 @@
                         .withRequiredArg()
                         .describedAs(getMessage("main.opt.main-class.arg"));
 
-        OptionSpec<Path> manPages
+        OptionSpec<List<Path>> manPages
                 = parser.accepts("man-pages", getMessage("main.opt.man-pages"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
-        OptionSpec<Path> modulePath
+        OptionSpec<List<Path>> modulePath
                 = parser.acceptsAll(Set.of("p", "module-path"),
                                     getMessage("main.opt.module-path"))
                         .withRequiredArg()
-                        .withValuesSeparatedBy(File.pathSeparatorChar)
                         .withValuesConvertedBy(DirPathConverter.INSTANCE);
 
         OptionSpec<Version> moduleVersion
@@ -1452,48 +1369,48 @@
             }
 
             if (opts.has(classPath))
-                options.classpath = opts.valuesOf(classPath);
+                options.classpath = getLastElement(opts.valuesOf(classPath));
             if (opts.has(cmds))
-                options.cmds = opts.valuesOf(cmds);
+                options.cmds = getLastElement(opts.valuesOf(cmds));
             if (opts.has(config))
-                options.configs = opts.valuesOf(config);
+                options.configs = getLastElement(opts.valuesOf(config));
             if (opts.has(dir))
-                options.extractDir = opts.valueOf(dir);
+                options.extractDir = getLastElement(opts.valuesOf(dir));
             if (opts.has(dryrun))
                 options.dryrun = true;
             if (opts.has(excludes))
-                options.excludes = opts.valuesOf(excludes);
+                options.excludes = opts.valuesOf(excludes);  // excludes is repeatable
             if (opts.has(libs))
-                options.libs = opts.valuesOf(libs);
+                options.libs = getLastElement(opts.valuesOf(libs));
             if (opts.has(headerFiles))
-                options.headerFiles = opts.valuesOf(headerFiles);
+                options.headerFiles = getLastElement(opts.valuesOf(headerFiles));
             if (opts.has(manPages))
-                options.manPages = opts.valuesOf(manPages);
+                options.manPages = getLastElement(opts.valuesOf(manPages));
             if (opts.has(legalNotices))
-                options.legalNotices = opts.valuesOf(legalNotices);
+                options.legalNotices = getLastElement(opts.valuesOf(legalNotices));
             if (opts.has(modulePath)) {
-                Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]);
+                Path[] dirs = getLastElement(opts.valuesOf(modulePath)).toArray(new Path[0]);
                 options.moduleFinder = new ModulePath(Runtime.version(), true, dirs);
             }
             if (opts.has(moduleVersion))
-                options.moduleVersion = opts.valueOf(moduleVersion);
+                options.moduleVersion = getLastElement(opts.valuesOf(moduleVersion));
             if (opts.has(mainClass))
-                options.mainClass = opts.valueOf(mainClass);
+                options.mainClass = getLastElement(opts.valuesOf(mainClass));
             if (opts.has(osName))
-                options.osName = opts.valueOf(osName);
+                options.osName = getLastElement(opts.valuesOf(osName));
             if (opts.has(osArch))
-                options.osArch = opts.valueOf(osArch);
+                options.osArch = getLastElement(opts.valuesOf(osArch));
             if (opts.has(osVersion))
-                options.osVersion = opts.valueOf(osVersion);
+                options.osVersion = getLastElement(opts.valuesOf(osVersion));
             if (opts.has(warnIfResolved))
-                options.moduleResolution = opts.valueOf(warnIfResolved);
+                options.moduleResolution = getLastElement(opts.valuesOf(warnIfResolved));
             if (opts.has(doNotResolveByDefault)) {
                 if (options.moduleResolution == null)
                     options.moduleResolution = ModuleResolution.empty();
                 options.moduleResolution = options.moduleResolution.withDoNotResolveByDefault();
             }
             if (opts.has(hashModules)) {
-                options.modulesToHash = opts.valueOf(hashModules);
+                options.modulesToHash = getLastElement(opts.valuesOf(hashModules));
                 // if storing hashes then the module path is required
                 if (options.moduleFinder == null)
                     throw new CommandException("err.modulepath.must.be.specified")
@@ -1531,6 +1448,13 @@
                 throw new CommandException("err.classpath.must.be.specified").showUsage(true);
             if (options.mainClass != null && !isValidJavaIdentifier(options.mainClass))
                 throw new CommandException("err.invalid.main-class", options.mainClass);
+            if (options.mode.equals(Mode.EXTRACT) && options.extractDir != null) {
+                try {
+                    Files.createDirectories(options.extractDir);
+                } catch (IOException ioe) {
+                    throw new CommandException("err.cannot.create.dir", options.extractDir);
+                }
+            }
         } catch (OptionException e) {
              throw new CommandException(e.getMessage());
         }
@@ -1558,6 +1482,12 @@
         return true;
     }
 
+    static <E> E getLastElement(List<E> list) {
+        if (list.size() == 0)
+            throw new InternalError("Unexpected 0 list size");
+        return list.get(list.size() - 1);
+    }
+
     private void reportError(String message) {
         out.println(getMessage("error.prefix") + " " + message);
     }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -108,9 +108,9 @@
 err.invalid.dryrun.option=--dry-run can only be used with hash mode
 err.module.descriptor.not.found=Module descriptor not found
 err.missing.export.or.open.packages=Packages that are exported or open in {0} are not present: {1}
+err.module.resolution.fail=Resolution failed: {0}
 warn.invalid.arg=Invalid classname or pathname not exist: {0}
 warn.no.module.hashes=No hashes recorded: no module specified for hashing depends on {0}
-warn.module.resolution.fail=No hashes recorded: {0}
 warn.ignore.entry=ignoring entry {0}, in section {1}
 warn.ignore.duplicate.entry=ignoring duplicate entry {0}, in section {1}
 
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c	Wed Jul 05 22:42:01 2017 +0200
@@ -418,7 +418,6 @@
   (JNIEnv *env, jclass klass, jint fd, jobject resultContainerObj,
    jlong address, jint length, jboolean peek) {
     SOCKETADDRESS sa;
-    int sa_len = sizeof(SOCKETADDRESS);
     ssize_t rv = 0;
     jlong *addr = jlong_to_ptr(address);
     struct iovec iov[1];
@@ -429,7 +428,7 @@
     /* Set up the msghdr structure for receiving */
     memset(msg, 0, sizeof (*msg));
     msg->msg_name = &sa;
-    msg->msg_namelen = sa_len;
+    msg->msg_namelen = sizeof(sa);
     iov->iov_base = addr;
     iov->iov_len = length;
     msg->msg_iov = iov;
@@ -538,7 +537,7 @@
    jobject targetAddress, jint targetPort, jint assocId, jint streamNumber,
    jboolean unordered, jint ppid) {
     SOCKETADDRESS sa;
-    int sa_len = sizeof(SOCKETADDRESS);
+    int sa_len = 0;
     ssize_t rv = 0;
     jlong *addr = jlong_to_ptr(address);
     struct iovec iov[1];
@@ -555,13 +554,12 @@
      *    Association already existing, assocId != -1, targetAddress = preferred addr
      */
     if (targetAddress != NULL /*&& assocId <= 0*/) {
-        if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, &sa.sa,
+        if (NET_InetAddressToSockaddr(env, targetAddress, targetPort, &sa,
                                       &sa_len, JNI_TRUE) != 0) {
             return IOS_THROWN;
         }
     } else {
-        memset(&sa, '\x0', sa_len);
-        sa_len = 0;
+        memset(&sa, '\x0', sizeof(sa));
     }
 
     /* Set up the msghdr structure for sending */
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c	Wed Jul 05 22:42:01 2017 +0200
@@ -211,22 +211,22 @@
   (JNIEnv *env, jclass klass, jint fd, jobjectArray addrs, jint port,
    jint addrsLength, jboolean add, jboolean preferIPv6) {
     SOCKETADDRESS *sap, *tmpSap;
-    int i, sa_len = sizeof(SOCKETADDRESS);
+    int i;
     jobject ia;
 
     if (addrsLength < 1)
         return;
 
-    if ((sap = calloc(addrsLength, sa_len)) == NULL) {
-          JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
+    if ((sap = calloc(addrsLength, sizeof(SOCKETADDRESS))) == NULL) {
+        JNU_ThrowOutOfMemoryError(env, "heap allocation failure");
         return;
     }
 
     tmpSap = sap;
     for (i = 0; i < addrsLength; i++) {
         ia = (*env)->GetObjectArrayElement(env, addrs, i);
-        if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr*)tmpSap,
-                                      &sa_len, preferIPv6) != 0) {
+        if (NET_InetAddressToSockaddr(env, ia, port, tmpSap, NULL,
+                                      preferIPv6) != 0) {
             free(sap);
             return;
         }
@@ -262,11 +262,11 @@
 Java_sun_nio_ch_sctp_SctpNet_connect0
   (JNIEnv *env, jclass clazz, int fd, jobject iao, jint port) {
     SOCKETADDRESS sa;
-    int sa_len = sizeof(SOCKETADDRESS);
+    int sa_len = 0;
     int rv;
 
-    if (NET_InetAddressToSockaddr(env, iao, port, &sa.sa,
-                                  &sa_len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
+                                  JNI_TRUE) != 0) {
         return IOS_THROWN;
     }
 
@@ -311,8 +311,7 @@
     }
 }
 
-void initializeISA
-  (JNIEnv* env) {
+void initializeISA(JNIEnv* env) {
     if (isaCls == 0) {
         jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
         CHECK_NULL(c);
@@ -325,8 +324,7 @@
     }
 }
 
-jobject SockAddrToInetSocketAddress
-  (JNIEnv *env, struct sockaddr* sap) {
+jobject SockAddrToInetSocketAddress(JNIEnv *env, SOCKETADDRESS *sap) {
     int port = 0;
 
     jobject ia = NET_SockaddrToInetAddress(env, sap, &port);
@@ -347,9 +345,9 @@
  * Signature: (I)[Ljava/net/SocketAddress;
  */
 JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0
-  (JNIEnv *env, jclass klass, jint fd) {
+  (JNIEnv *env, jclass klass, jint fd)
+{
     void *addr_buf, *laddr;
-    struct sockaddr* sap;
     int i, addrCount;
     jobjectArray isaa;
 
@@ -377,38 +375,35 @@
     }
 
     laddr = addr_buf;
-    for (i=0; i<addrCount; i++) {
+    for (i = 0; i < addrCount; i++) {
         int port = 0;
-        jobject isa = NULL, ia;
-        sap = (struct sockaddr*)addr_buf;
-        ia = NET_SockaddrToInetAddress(env, sap, &port);
+        jobject ia, isa = NULL;
+        ia = NET_SockaddrToInetAddress(env, (SOCKETADDRESS *)addr_buf, &port);
         if (ia != NULL)
             isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
         if (isa == NULL)
             break;
         (*env)->SetObjectArrayElement(env, isaa, i, isa);
 
-        if (sap->sa_family == AF_INET)
-            addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
+        if (((struct sockaddr *)addr_buf)->sa_family == AF_INET)
+            addr_buf = ((struct sockaddr_in *)addr_buf) + 1;
         else
-            addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
+            addr_buf = ((struct sockaddr_in6 *)addr_buf) + 1;
     }
 
     nio_sctp_freeladdrs(laddr);
     return isaa;
 }
 
-jobjectArray getRemoteAddresses
-  (JNIEnv *env, jint fd, sctp_assoc_t id) {
+jobjectArray getRemoteAddresses(JNIEnv *env, jint fd, sctp_assoc_t id) {
     void *addr_buf, *paddr;
-    struct sockaddr* sap;
     int i, addrCount;
     jobjectArray isaa;
 
 #if __solaris__
     if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
 #else /* __linux__ */
-    if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr**)&addr_buf)) == -1) {
+    if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr **)&addr_buf)) == -1) {
 #endif
         handleSocketError(env, errno);
         return NULL;
@@ -429,25 +424,23 @@
     }
 
     paddr = addr_buf;
-    for (i=0; i<addrCount; i++) {
-        jobject ia, isa = NULL;
+    for (i = 0; i < addrCount; i++) {
         int port = 0;
-        sap = (struct sockaddr*)addr_buf;
-        ia = NET_SockaddrToInetAddress(env, sap, &port);
+        jobject ia, isa = NULL;
+        ia = NET_SockaddrToInetAddress(env, (SOCKETADDRESS *)addr_buf, &port);
         if (ia != NULL)
             isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
         if (isa == NULL)
             break;
         (*env)->SetObjectArrayElement(env, isaa, i, isa);
 
-        if (sap->sa_family == AF_INET)
-            addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
+        if (((struct sockaddr *)addr_buf)->sa_family == AF_INET)
+            addr_buf = ((struct sockaddr_in *)addr_buf) + 1;
         else
-            addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
+            addr_buf = ((struct sockaddr_in6 *)addr_buf) + 1;
     }
 
     nio_sctp_freepaddrs(paddr);
-
     return isaa;
 }
 
@@ -579,7 +572,6 @@
   (JNIEnv *env, jclass klass, jint fd, jint assocId) {
     struct sctp_setprim prim;
     unsigned int prim_len = sizeof(prim);
-    struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
 
     prim.ssp_assoc_id = assocId;
 
@@ -589,7 +581,7 @@
         return NULL;
     }
 
-    return SockAddrToInetSocketAddress(env, sap);
+    return SockAddrToInetSocketAddress(env, (SOCKETADDRESS *)&prim.ssp_addr);
 }
 
 /*
@@ -600,11 +592,10 @@
 JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setPrimAddrOption0
   (JNIEnv *env, jclass klass, jint fd, jint assocId, jobject iaObj, jint port) {
     struct sctp_setprim prim;
-    struct sockaddr* sap = (struct sockaddr*)&prim.ssp_addr;
-    int sap_len = sizeof(sap);
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
-                                  &sap_len, JNI_TRUE) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, port,
+                                  (SOCKETADDRESS *)&prim.ssp_addr,
+                                  NULL, JNI_TRUE) != 0) {
         return;
     }
 
@@ -625,18 +616,17 @@
   (JNIEnv *env, jclass klass, jint fd, jint assocId,
    jobject iaObj, jint port, jboolean preferIPv6) {
     struct sctp_setpeerprim prim;
-    struct sockaddr* sap = (struct sockaddr*)&prim.sspp_addr;
-    int sap_len = sizeof(sap);
 
-    if (NET_InetAddressToSockaddr(env, iaObj, port, sap,
-                                  &sap_len, preferIPv6) != 0) {
+    if (NET_InetAddressToSockaddr(env, iaObj, port,
+                                  (SOCKETADDRESS *)&prim.sspp_addr,
+                                  NULL, preferIPv6) != 0) {
         return;
     }
 
     prim.sspp_assoc_id = assocId;
 
     if (setsockopt(fd, IPPROTO_SCTP, SCTP_SET_PEER_PRIMARY_ADDR, &prim,
-            sizeof(prim)) < 0) {
+                   sizeof(prim)) < 0) {
         JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                      "sun.nio.ch.SctpNet.setPeerPrimAddrOption0");
     }
--- a/jdk/test/ProblemList.txt	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 22:42:01 2017 +0200
@@ -1,6 +1,6 @@
 ###########################################################################
 #
-# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -141,8 +141,6 @@
 
 # jdk_io
 
-java/io/pathNames/GeneralWin32.java                             8156595 windows-all
-
 ############################################################################
 
 # jdk_management
@@ -203,8 +201,6 @@
 
 sun/rmi/rmic/newrmic/equivalence/run.sh                         8145980 generic-all
 
-java/rmi/registry/readTest/readTest.sh                          7146543 generic-all
-
 ############################################################################
 
 # jdk_security
@@ -262,6 +258,8 @@
 
 tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java       8169971 windows-x64
 
+tools/jmod/JmodTest.java                                        8172870 windows-all
+
 ############################################################################
 
 # jdk_jdi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/NormalToIconified/NormalToIconifiedTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8171949
+ * @summary Tests that bitwise mask is set and state listener is notified during state transition.
+ * @author Dmitry Markov
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main NormalToIconifiedTest
+ */
+
+import java.awt.Frame;
+import java.awt.Robot;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowStateListener;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class NormalToIconifiedTest {
+    private static final AtomicBoolean listenerNotified = new AtomicBoolean(false);
+
+    public static void main(String[] args) {
+        Robot robot = Util.createRobot();
+
+        Frame testFrame = new Frame("Test Frame");
+        testFrame.setSize(200, 200);
+        testFrame.addWindowStateListener(new WindowStateListener() {
+            @Override
+            public void windowStateChanged(WindowEvent e) {
+                listenerNotified.set(true);
+                synchronized (listenerNotified) {
+                    listenerNotified.notifyAll();
+                }
+            }
+        });
+        testFrame.setVisible(true);
+
+        Frame mainFrame = new Frame("Main Frame");
+        mainFrame.setSize(200, 200);
+        mainFrame.setLocationRelativeTo(null);
+        mainFrame.setVisible(true);
+
+        Util.waitForIdle(robot);
+
+        try {
+            Util.clickOnComp(mainFrame, robot);
+            Util.waitForIdle(robot);
+
+            // NORMAL -> ICONIFIED
+            listenerNotified.set(false);
+            testFrame.setExtendedState(Frame.ICONIFIED);
+            Util.waitForIdle(robot);
+
+            Util.waitForCondition(listenerNotified, 2000);
+            if (!listenerNotified.get()) {
+                throw new RuntimeException("Test FAILED! Window state listener was not notified during NORMAL to" +
+                        "ICONIFIED transition");
+            }
+            if (testFrame.getExtendedState() != Frame.ICONIFIED) {
+                throw new RuntimeException("Test FAILED! Frame is not in ICONIFIED state");
+            }
+
+            // ICONIFIED -> NORMAL
+            listenerNotified.set(false);
+            testFrame.setExtendedState(Frame.NORMAL);
+            Util.waitForIdle(robot);
+
+            Util.waitForCondition(listenerNotified, 2000);
+            if (!listenerNotified.get()) {
+                throw new RuntimeException("Test FAILED! Window state listener was not notified during ICONIFIED to" +
+                        "NORMAL transition");
+            }
+            if (testFrame.getExtendedState() != Frame.NORMAL) {
+                throw new RuntimeException("Test FAILED! Frame is not in NORMAL state");
+            }
+        } finally {
+            testFrame.dispose();
+            mainFrame.dispose();
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/ObscuredFrame/ObscuredFrameTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8171952
+ * @summary Tests that getMousePosition() returns null for obscured component.
+ * @author Dmitry Markov
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main ObscuredFrameTest
+ */
+
+import java.awt.*;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class ObscuredFrameTest {
+    public static void main(String[] args) {
+        Robot robot = Util.createRobot();
+
+        Frame frame = new Frame("Obscured Frame");
+        frame.setSize(200, 200);
+        frame.setLocationRelativeTo(null);
+        Button button = new Button("Button");
+        frame.add(button);
+
+        Dialog dialog = new Dialog(frame, "Visible Dialog", false);
+        dialog.setSize(200, 200);
+        dialog.setLocationRelativeTo(null);
+        dialog.setVisible(true);
+
+        frame.setVisible(true);
+
+        Util.waitForIdle(robot);
+
+        Util.pointOnComp(button, robot);
+        Util.waitForIdle(robot);
+
+        try {
+            if (button.getMousePosition() != null) {
+                throw new RuntimeException("Test Failed! Mouse position is not null for obscured component.");
+            }
+        } finally {
+            frame.dispose();
+            dialog.dispose();
+        }
+    }
+}
+
--- a/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -23,7 +23,7 @@
 
 /* @test
    @key headful
-   @bug      8166897
+   @bug      8166897 8167652
    @summary  Some font overlap in the Optionpane dialog.
    @run      main ChangeWindowResizabiltyTest
 */
@@ -34,41 +34,75 @@
 import java.awt.Frame;
 import java.awt.Panel;
 import java.awt.Robot;
+import java.awt.Point;
 
 public class ChangeWindowResizabiltyTest {
     public static void main(String[] args) throws Exception {
         Robot robot = new Robot();
         for(int i = 0; i < 10; i++) {
             Dialog dialog = new Dialog((Frame) null);
+            dialog.setLocation(100, 100);
             Component panel = new Panel();
             panel.setPreferredSize(new Dimension(200, 100));
             dialog.add(panel);
             dialog.pack();
             dialog.setVisible(true);
+            robot.waitForIdle();
+            robot.delay(200);
+
+            Point frameLoc = dialog.getLocationOnScreen();
+            Point contentLoc = panel.getLocationOnScreen();
+
+            System.out.println("Decor location " + frameLoc);
+            System.out.println("Content location " + contentLoc);
 
             dialog.setResizable(false);
             robot.waitForIdle();
             robot.delay(200);
 
-            System.out.println(panel.getLocationOnScreen());
-            System.out.println(dialog.getLocationOnScreen());
+            Point l = dialog.getLocationOnScreen();
+            if (!l.equals(frameLoc)) {
+                dialog.dispose();
+                throw new RuntimeException("Decorated frame location moved " +
+                        "after setResizable(false)" + l);
+            }
+
+            l = panel.getLocationOnScreen();
+            if (!l.equals(contentLoc)) {
+                dialog.dispose();
+                throw new RuntimeException("Content location moved after " +
+                        "setResizable(false)" + l);
+            }
+
             if (panel.getLocationOnScreen().y <
-                       dialog.getLocationOnScreen().y + dialog.getInsets().top) {
+                      dialog.getLocationOnScreen().y + dialog.getInsets().top) {
                 dialog.dispose();
                 throw new RuntimeException(
-                        "Wrong content position after setResizable(false)");
+                            "Wrong content position after setResizable(false)");
             }
 
             dialog.setResizable(true);
             robot.waitForIdle();
             robot.delay(200);
-            System.out.println(panel.getLocationOnScreen());
-            System.out.println(dialog.getLocationOnScreen());
+
+            l = dialog.getLocationOnScreen();
+            if (!l.equals(frameLoc)) {
+                dialog.dispose();
+                throw new RuntimeException("Decorated frame location moved " +
+                        "after setResizable(true)" + l);
+            }
+
+            l = panel.getLocationOnScreen();
+            if (!l.equals(contentLoc)) {
+                dialog.dispose();
+                throw new RuntimeException("Content location moved after " +
+                        "setResizable(true)" + l);
+            }
             if (panel.getLocationOnScreen().y <
-                    dialog.getLocationOnScreen().y + dialog.getInsets().top) {
+                      dialog.getLocationOnScreen().y + dialog.getInsets().top) {
                 dialog.dispose();
                 throw new RuntimeException(
-                        "Wrong content position after setResizable(true)");
+                             "Wrong content position after setResizable(true)");
             }
 
             dialog.dispose();
--- a/jdk/test/java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -22,7 +22,6 @@
  */
 
 import sun.awt.image.MultiResolutionToolkitImage;
-import sun.java2d.SunGraphics2D;
 
 import javax.swing.*;
 import java.awt.*;
@@ -37,7 +36,6 @@
  * @summary [macosx] Drag image of TransferHandler does not honor
  * MultiResolutionImage
  * @modules java.desktop/sun.awt.image
- *          java.desktop/sun.java2d
  * @run main MultiResolutionDragImageTest TEST_DRAG
  */
 public class MultiResolutionDragImageTest {
@@ -126,30 +124,11 @@
         return Math.abs(n - m) <= 50;
     }
 
-    private static float getScaleFactor() {
-
-        final Dialog dialog = new Dialog((Window) null);
-        dialog.setSize(100, 100);
-        dialog.setModal(true);
-        final float[] scaleFactors = new float[1];
-        Panel panel = new Panel() {
-
-            @Override
-            public void paint(Graphics g) {
-                float scaleFactor = 1;
-                if (g instanceof SunGraphics2D) {
-                    scaleFactor = ((SunGraphics2D) g).surfaceData.getDefaultScale();
-                }
-                scaleFactors[0] = scaleFactor;
-                dialog.setVisible(false);
-            }
-        };
-
-        dialog.add(panel);
-        dialog.setVisible(true);
-        dialog.dispose();
-
-        return scaleFactors[0];
+    static float getScaleFactor() {
+        return (float) GraphicsEnvironment.
+                getLocalGraphicsEnvironment().
+                getDefaultScreenDevice().getDefaultConfiguration().
+                getDefaultTransform().getScaleX();
     }
 
     private static Image createMultiResolutionImage() {
--- a/jdk/test/java/awt/font/GlyphVector/TestLayoutFlags.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/awt/font/GlyphVector/TestLayoutFlags.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 
 /* @test
-   @bug 4328745 5090704
+   @bug 4328745 5090704 8166111
    @summary exercise getLayoutFlags, getGlyphCharIndex, getGlyphCharIndices
  */
 
@@ -82,7 +82,7 @@
         test("latin", latinGV, GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS);
         test("hebrew", hebrewGV, GlyphVector.FLAG_RUN_RTL |
              GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS);
-        test("arabic", arabicGV, GlyphVector.FLAG_RUN_RTL |
+        test("arabic", arabicGV, GlyphVector.FLAG_COMPLEX_GLYPHS |
              GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS);
         test("hindi", hindiGV, GlyphVector.FLAG_COMPLEX_GLYPHS |
              GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/Raster/TestChildRasterOp.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8130737 8172559
+ * @summary test no exception rasterop for child raster with non-zero offset
+ */
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+public class TestChildRasterOp {
+
+    private static AffineTransform at = new AffineTransform();
+    private static final AffineTransformOp rop =
+        new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
+    private static int[] offsets = {0};
+
+    public static void main(String[] args) {
+        testByteRaster();
+        testShortRaster();
+        testIntRaster();
+    }
+
+    private static void testByteRaster() {
+        WritableRaster srcRaster, dstRaster;
+
+        byte[] pixels =
+            { 11, 12, 13, 14,
+              21, 22, 23, 24,
+              31, 32, 33, 34,
+              41, 42, 43, 44 };
+
+        DataBuffer db = new DataBufferByte(pixels, pixels.length);
+        srcRaster =
+            Raster.createInterleavedRaster(db, 4, 4, 4, 1, offsets, null);
+        srcRaster = srcRaster.createWritableChild(1, 1, 3, 3, 0, 0, null);
+        dstRaster = rop.filter(srcRaster, null);
+    }
+
+    private static void testShortRaster() {
+        WritableRaster srcRaster, dstRaster;
+
+        short[] pixels =
+            { 11, 12, 13, 14,
+              21, 22, 23, 24,
+              31, 32, 33, 34,
+              41, 42, 43, 44 };
+
+        DataBuffer db = new DataBufferUShort(pixels, pixels.length);
+        srcRaster =
+            Raster.createInterleavedRaster(db, 4, 4, 4, 1, offsets, null);
+        srcRaster = srcRaster.createWritableChild(1, 1, 3, 3, 0, 0, null);
+        dstRaster = rop.filter(srcRaster, null);
+    }
+
+    private static void testIntRaster() {
+        WritableRaster srcRaster, dstRaster;
+
+        int[] pixels =
+            { 11, 12, 13, 14,
+              21, 22, 23, 24,
+              31, 32, 33, 34,
+              41, 42, 43, 44 };
+
+        DataBuffer db = new DataBufferInt(pixels, pixels.length);
+        srcRaster =
+            Raster.createPackedRaster(db, 4, 4, 4,  offsets, null);
+        srcRaster = srcRaster.createWritableChild(1, 1, 3, 3, 0, 0, null);
+        dstRaster = rop.filter(srcRaster, null);
+    }
+}
--- a/jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java	Wed Jul 05 22:42:01 2017 +0200
@@ -24,16 +24,28 @@
 /*
  * @test
  * @key headful
- * @bug 7108598
+ * @bug 7108598 8172009
  * @summary Container.paint/KeyboardFocusManager.clearMostRecentFocusOwner methods deadlock
  * @library ../../regtesthelpers
  * @author Oleg Pekhovskiy
  * @build Util
- * @run main/timeout=20 PaintSetEnabledDeadlock
+ * @run main PaintSetEnabledDeadlock
  */
 
-import java.awt.*;
-import java.awt.event.*;
+import java.awt.Button;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.Panel;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import test.java.awt.regtesthelpers.Util;
 
 public class PaintSetEnabledDeadlock extends Frame {
--- a/jdk/test/java/awt/print/PrinterJob/BannerTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/awt/print/PrinterJob/BannerTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -22,7 +22,7 @@
  */
 /*
  * @test
- * @bug 6575247
+ * @bug 6575247 8170579
  * @summary  Verifies if Banner page is printed
  * @requires (os.family == "linux" | os.family == "solaris")
  * @run main/manual BannerTest
@@ -39,6 +39,9 @@
 import static java.awt.print.Printable.PAGE_EXISTS;
 import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
+import javax.print.PrintService;
+import javax.print.attribute.standard.JobSheets;
+import javax.print.attribute.standard.SheetCollate;
 import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.JPanel;
@@ -50,8 +53,18 @@
     private static Thread mainThread;
     private static boolean testPassed;
     private static boolean testGeneratedInterrupt;
+    private static volatile PrinterJob job;
 
     public static void main(String[] args)  throws Exception {
+        job = PrinterJob.getPrinterJob();
+        PrintService prtSrv = job.getPrintService();
+        if (job.getPrintService() == null) {
+            System.out.println("No printers. Test cannot continue");
+            return;
+        }
+        if (!prtSrv.isAttributeCategorySupported(JobSheets.class)) {
+            return;
+        }
         SwingUtilities.invokeAndWait(() -> {
             doTest(BannerTest::printTest);
         });
@@ -69,11 +82,6 @@
     }
 
     private static void printTest() {
-        PrinterJob job = PrinterJob.getPrinterJob();
-        if (job.getPrintService() == null) {
-            System.out.println("No printers. Test cannot continue");
-            return;
-        }
         job.setPrintable(new BannerTest());
         if(job.printDialog()) {
             try {
--- a/jdk/test/java/awt/print/PrinterJob/TestCheckSystemDefaultBannerOption.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/awt/print/PrinterJob/TestCheckSystemDefaultBannerOption.java	Wed Jul 05 22:42:01 2017 +0200
@@ -22,7 +22,7 @@
  */
 /*
  * @test
- * @bug 8165947
+ * @bug 8165947 8170579
  * @summary  Verifies System default banner page option is honoured by jdk
  * @requires (os.family == "linux" | os.family == "solaris")
  * @run main/manual TestCheckSystemDefaultBannerOption
@@ -38,6 +38,7 @@
 import static java.awt.print.Printable.PAGE_EXISTS;
 import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
+import javax.print.PrintService;
 import javax.print.attribute.standard.JobSheets;
 import javax.swing.JButton;
 import javax.swing.JDialog;
@@ -56,10 +57,15 @@
     public static void main (String[] args) throws Exception {
 
         job = PrinterJob.getPrinterJob();
-        if (job.getPrintService() == null) {
+        PrintService prtSrv = job.getPrintService();
+        if (prtSrv == null) {
             System.out.println("No printers. Test cannot continue");
             return;
         }
+        // do not run the test if JobSheet category is not supported
+        if (!prtSrv.isAttributeCategorySupported(JobSheets.class)) {
+            return;
+        }
         // check system default banner option and let user know what to expect
         JobSheets js = (JobSheets)job.getPrintService().
                 getDefaultAttributeValue(JobSheets.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/File/WinDirRelative.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8153250
+ * @summary Tests that files are correctly listed for a directory-relative path
+ * @requires (os.family == "windows")
+ */
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class WinDirRelative {
+    private static final char COLON = ':';
+    private static final String BASENAME = "TestFile_";
+    private static final String EXTENSION = ".txt";
+    private static final int NUM_FILES = 10;
+
+    private static boolean isLetter(char c) {
+        return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
+    }
+
+    public static void main(String[] args) throws Throwable {
+        // Get the working directory which is also the default
+        // directory for the current drive.
+        String userDir = System.getProperty("user.dir");
+
+        // Test only if a leading drive letter is found
+        if (isLetter(userDir.charAt(0)) && userDir.charAt(1) == COLON) {
+            // Create some empty files
+            List<String> filenames = new ArrayList<String>(NUM_FILES);
+            for (int i = 0; i < NUM_FILES; i++) {
+                String filename = BASENAME + i + EXTENSION;
+                filenames.add(filename);
+                File f = new File(filename);
+                f.createNewFile();
+                f.deleteOnExit();
+                System.out.printf("Created %s (%s)%n", filename,
+                    f.getAbsolutePath());
+            }
+
+            // List files and verify that the ones with recognized names exist.
+            String prefix = userDir.substring(0, 2);
+            File p = new File(prefix);
+            int failures = 0;
+            int successes = 0;
+            for (File f : p.listFiles()) {
+                if (f.getName().toString().startsWith(BASENAME)) {
+                    if (!f.exists()) {
+                        System.err.printf("%s (%s) does not exist%n", f,
+                            f.getAbsolutePath());
+                        failures++;
+                    } else {
+                        successes++;
+                    }
+                }
+            }
+
+            // Fail if there was an existence test failure or if not
+            // enough of the created files were found
+            boolean testFailed = false;
+            if (failures > 0) {
+                System.err.println("Existence check failed");
+                testFailed = true;
+            }
+            if (successes != NUM_FILES) {
+                System.err.println("Count check failed");
+                testFailed = true;
+            }
+            if (testFailed) {
+                throw new RuntimeException("Test failed");
+            }
+        }
+    }
+}
--- a/jdk/test/java/io/File/createTempFile/Patterns.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/io/File/createTempFile/Patterns.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 4152178
+   @bug 4152178 8152272
    @summary Check various temp-file prefix/suffix cases */
 
 import java.io.File;
@@ -66,6 +66,7 @@
         cky("xxx", "");
         cky("xxx", "y");
         cky("xxx", ".y");
+        cky("xyz", "Directory" + System.getProperty("file.separator"));
     }
 
 }
--- a/jdk/test/java/io/pathNames/General.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/io/pathNames/General.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
     private static int gensymCounter = 0;
 
     protected static final String userDir = System.getProperty("user.dir");
+    protected static final String workSubDir = "tmp";
 
     protected static String baseDir = null;
     protected static String relative = null;
@@ -60,7 +61,10 @@
      *                  direct or indirect calling) in a whole test.
      */
     protected static void initTestData(int depth) throws IOException {
-        File parent = new File(userDir);
+        File parent = new File(userDir + File.separator + workSubDir);
+        if (!parent.mkdir()) {
+            throw new IOException("Fail to create directory: " + parent);
+        }
         for (int i = 0; i < depth; i++) {
             File tmp = new File(parent, gensym());
             tmp.createNewFile();
--- a/jdk/test/java/io/pathNames/GeneralWin32.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/io/pathNames/GeneralWin32.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,8 @@
     private static void checkCaseLookup() throws IOException {
         /* Use long names here to avoid 8.3 format, which Samba servers often
            force to lowercase */
-        File d = new File("XyZzY0123", "FOO_bar_BAZ");
+        File r = new File (workSubDir, "XyZzY0123");
+        File d = new File(r, "FOO_bar_BAZ");
         File f = new File(d, "GLORPified");
         if (!f.exists()) {
             if (!d.exists()) {
@@ -74,9 +75,9 @@
            case of filenames, rather than just using the input case */
         File y = new File(userDir, f.getPath());
         String ans = y.getPath();
-        check(ans, "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
-        check(ans, "xyzzy0123\\foo_bar_baz\\glorpified");
-        check(ans, "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
+        check(ans, workSubDir + File.separator + "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
+        check(ans, workSubDir + File.separator + "xyzzy0123\\foo_bar_baz\\glorpified");
+        check(ans, workSubDir + File.separator + "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
     }
 
     private static void checkWild(File f) throws Exception {
@@ -125,20 +126,19 @@
         throw new RuntimeException("Can't find an active drive");
     }
 
-    private static void checkDrive(int depth, char drive, boolean exists)
+    private static void checkDrive(int depth, String drive, boolean exists)
         throws Exception
     {
-        String d = drive + ":";
-        File df = new File(d);
-        String ans = exists ? df.getAbsolutePath() : d;
+        File df = new File(drive);
+        String ans = exists ? df.getAbsolutePath() : drive;
         if (!ans.endsWith("\\"))
             ans = ans + "\\";
-        checkNames(depth, false, ans, d);
+        checkNames(depth, false, ans, drive);
     }
 
     private static void checkDrivePaths(int depth) throws Exception {
-        checkDrive(depth, findActiveDrive(), true);
-        checkDrive(depth, findInactiveDrive(), false);
+        checkDrive(depth, findActiveDrive() + ":" + workSubDir + File.separator, true);
+        checkDrive(depth, findInactiveDrive() + ":", false);
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/URLConnection/SetDefaultUseCaches.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8163449
+ * @summary Allow per protocol setting for URLConnection defaultUseCaches
+ * @run main/othervm SetDefaultUseCaches
+ */
+
+import java.net.*;
+import java.io.*;
+
+public class SetDefaultUseCaches {
+    static void testAssert(boolean value, boolean comparator) {
+        if (value != comparator) {
+            System.err.println("Expected " + comparator + " Got " + value);
+            throw new RuntimeException("Test failed:");
+        } else
+            System.err.println("OK");
+    }
+
+    public static void main(String s[]) throws Exception {
+        URL url = new URL("http://www.foo.com/");
+        URL url1 = new URL("file:///a/b.txt");
+
+        // check default default is true
+        URLConnection urlc = url.openConnection();
+        testAssert(urlc.getDefaultUseCaches(), true);
+
+        // set default for http to false and check
+        URLConnection.setDefaultUseCaches("HTTP", false);
+
+        urlc = url.openConnection();
+        testAssert(urlc.getDefaultUseCaches(), true);
+        testAssert(urlc.getUseCaches(), false);
+        testAssert(URLConnection.getDefaultUseCaches("http"), false);
+
+        URLConnection urlc1 = url1.openConnection();
+        testAssert(urlc1.getDefaultUseCaches(), true);
+
+        // set default default to false and check other values the same
+        urlc.setDefaultUseCaches(false);
+        urlc1.setDefaultUseCaches("fiLe", true);
+        testAssert(urlc1.getDefaultUseCaches(), false);
+        testAssert(URLConnection.getDefaultUseCaches("fiLE"), true);
+    }
+}
--- a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,9 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary JavaVM RMID TestSecurityManager
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider RegistryVM RMIRegistryRunner
+ *        TestSecurityManager
  * @run main/othervm AltSecurityManager
  */
 
@@ -44,7 +46,6 @@
  * if registry and rmid take too long to exit.
  */
 public class AltSecurityManager implements Runnable {
-    private final int regPort;
     // variable to hold registry and rmid children
     static JavaVM vm = null;
 
@@ -57,31 +58,34 @@
     private static final long TIME_OUT =
             (long)(15000 * TestLibrary.getTimeoutFactor());
 
-    public AltSecurityManager(int port) {
-        if (port <= 0) {
-            TestLibrary.bomb("Port must be greater than 0.");
-        }
-
-        this.regPort = port;
-    }
-
     public void run() {
         try {
             if (utilityToStart.equals(REGISTRY_IMPL)) {
-                vm = new JavaVM(utilityToStart,
-                        " -Djava.security.manager=TestSecurityManager",
-                        Integer.toString(regPort));
+                vm = RegistryVM.createRegistryVMWithRunner(
+                        "RMIRegistryRunner",
+                        "-Djava.security.manager=TestSecurityManager");
             } else if (utilityToStart.contains(ACTIVATION)) {
-                vm = new JavaVM(utilityToStart,
-                        " -Djava.security.manager=TestSecurityManager",
-                        "-port " + Integer.toString(regPort));
+                vm = RMID.createRMIDOnEphemeralPortWithOptions(
+                        "-Djava.security.manager=TestSecurityManager");
             } else {
                 TestLibrary.bomb("Utility to start must be " + REGISTRY_IMPL +
                         " or " + ACTIVATION);
             }
 
             System.err.println("starting " + utilityToStart);
-            vm.execute();
+            try {
+                vm.start();
+                throw new RuntimeException("Expected exception did not occur!");
+            } catch (Exception expected) {
+                int exit = vm.waitFor();
+                if (exit != TestSecurityManager.EXIT_VALUE) {
+                    throw new RuntimeException(utilityToStart
+                            + " exit with an unexpected value "
+                            + exit + ".");
+                }
+                System.err.format("Success: starting %s exited with status %d%n",
+                                  utilityToStart, TestSecurityManager.EXIT_VALUE);
+            }
 
         } catch (Exception e) {
             TestLibrary.bomb(e);
@@ -96,8 +100,7 @@
         utilityToStart = utility;
 
         try {
-            int port = TestLibrary.getUnusedRandomPort();
-            Thread thread = new Thread(new AltSecurityManager(port));
+            Thread thread = new Thread(new AltSecurityManager());
             System.err.println("expecting RuntimeException for " +
                                "checkListen in child process");
             long start = System.currentTimeMillis();
@@ -116,7 +119,7 @@
                                    " terminated on time");
             }
         } finally {
-            vm.destroy();
+            vm.cleanup();
             vm = null;
         }
     }
--- a/jdk/test/java/rmi/registry/altSecurityManager/TestSecurityManager.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/registry/altSecurityManager/TestSecurityManager.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,8 @@
 /**/
 
 public class TestSecurityManager extends SecurityManager {
+    public static final int EXIT_VALUE = 123;
+
     public TestSecurityManager() {
     }
 
@@ -36,7 +38,7 @@
         // by the main test process to detect that the proper security
         // manager has been installed in the relevant VMs.
         //
-        System.exit(1);
+        System.exit(EXIT_VALUE);
     }
 
     public void checkExit(int status) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/altSecurityManager/registry.security.policy	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,8 @@
+grant {
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry";
+  permission java.util.PropertyPermission "env.class.path", "read";
+  permission java.io.FilePermission ".", "read";
+  permission java.util.PropertyPermission "user.dir", "read";
+  permission java.lang.RuntimePermission "createClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/altSecurityManager/rmid.security.policy	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,7 @@
+grant {
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
+  permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.port", "read";
+  permission java.util.PropertyPermission "test.java.rmi.testlibrary.RMIDSelectorProvider.timeout", "read";
+  permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept";
+};
--- a/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary Dummy
+ * @build TestLibrary Dummy RegistryVM RMIRegistryRunner
  * @run main/othervm/policy=security.policy
  *     -Djava.rmi.server.useCodebaseOnly=false ClassPathCodebase
  */
@@ -48,8 +48,9 @@
 
 public class ClassPathCodebase {
 
-    /** wait 10 seconds for the registry process to be ready to call */
-    private final static long REGISTRY_WAIT = 15000;
+    /** wait dozens of seconds for the registry process to be ready to call */
+    private static final long REGISTRY_WAIT =
+            (long)(10000 * TestLibrary.getTimeoutFactor());
 
     private final static String dummyClassName = "Dummy";
 
@@ -64,7 +65,7 @@
 
         TestLibrary.suggestSecurityManager("java.lang.SecurityManager");
 
-        Process rmiregistry = null;
+        RegistryVM rmiregistry = null;
 
         try {
             /*
@@ -82,27 +83,13 @@
              * Spawn an rmiregistry in the "import" codebase directory.
              */
             File rmiregistryDir =
-                new File(System.getProperty("user.dir", "."), importCodebase);
-
-            String rmiregistryCommand =
-                System.getProperty("java.home") + File.separator +
-                "bin" + File.separator + "rmiregistry";
-
-            int port = TestLibrary.getUnusedRandomPort();
-            String cmdarray[] = new String[] {
-                rmiregistryCommand,
-                "-J-Denv.class.path=.",
-                "-J-Djava.rmi.server.codebase=" + exportCodebaseURL,
-                Integer.toString(port) };
-
-            System.err.println("\nCommand used to spawn rmiregistry process:");
-            System.err.println("\t" + Arrays.asList(cmdarray).toString());
-
-            rmiregistry = Runtime.getRuntime().exec(cmdarray, null, rmiregistryDir);
-
-            // pipe rmiregistry output to our output, for debugging failures
-            StreamPipe.plugTogether(rmiregistry.getInputStream(), System.err);
-            StreamPipe.plugTogether(rmiregistry.getErrorStream(), System.err);
+                  new File(System.getProperty("user.dir", "."), importCodebase);
+            rmiregistry = RegistryVM.createRegistryVMWithRunner("RMIRegistryRunner",
+                            " -Denv.class.path=."
+                            + " -Djava.rmi.server.codebase=" + exportCodebaseURL
+                            + " -Duser.dir=" + rmiregistryDir.getAbsolutePath());
+            rmiregistry.start();
+            int port = rmiregistry.getPort();
 
             /*
              * Wait for the registry to initialize and be ready to call.
@@ -174,7 +161,7 @@
             throw new RuntimeException("TEST FAILED: " + e.toString());
         } finally {
             if (rmiregistry != null) {
-                rmiregistry.destroy();
+                rmiregistry.cleanup();
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/classPathCodebase/registry.security.policy	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,18 @@
+/*
+ * security policy used by the registry process started by RegistryVM.
+ */
+
+grant {
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry";
+  permission java.util.PropertyPermission "env.class.path", "read";
+  permission java.io.FilePermission ".", "read";
+  permission java.util.PropertyPermission "user.dir", "read";
+  permission java.lang.RuntimePermission "createClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+  permission java.io.FilePermission ".-Djava.rmi.server.codebase=file", "read";
+  permission java.io.FilePermission ".${/}-", "read";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp";
+  permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept";
+};
--- a/jdk/test/java/rmi/registry/classPathCodebase/security.policy	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/registry/classPathCodebase/security.policy	Wed Jul 05 22:42:01 2017 +0200
@@ -18,6 +18,12 @@
   // test needs to use java to exec an rmiregistry
   permission java.io.FilePermission "${java.home}${/}bin${/}-", "execute";
 
-  // test needs to communicate with this its registry
+  // test needs to communicate with its registry
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.util.PropertyPermission "java.security.policy", "read";
+  permission java.util.PropertyPermission "java.security.manager", "read";
+
+  // used by TestLibrary to determine extra commandline properties
+  permission java.io.FilePermission "..${/}..${/}test.props", "read";
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/CodebaseTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7102369 7094468 7100592
+ * @modules java.rmi/sun.rmi.registry
+ *          java.rmi/sun.rmi.server
+ *          java.rmi/sun.rmi.transport
+ *          java.rmi/sun.rmi.transport.tcp
+ * @library ../../testlibrary
+ * @build TestLibrary RMIRegistryRunner RegistryVM JavaVM testPkg.* RegistryLookup
+ * @summary remove java.rmi.server.codebase property parsing from registyimpl
+ * @run main/othervm CodebaseTest
+*/
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+public class CodebaseTest {
+
+    public static void main(String args[]) throws Exception {
+        RegistryVM rmiregistry = null;
+        JavaVM client = null;
+        try {
+            File src = new File(System.getProperty("test.classes", "."), "testPkg");
+            File dest = new File(System.getProperty("user.dir", "."), "testPkg");
+            Files.move(src.toPath(), dest.toPath(),
+                    StandardCopyOption.REPLACE_EXISTING);
+
+            File rmiregistryDir =
+                new File(System.getProperty("user.dir", "."), "rmi_tmp");
+            rmiregistryDir.mkdirs();
+            rmiregistry = RegistryVM.createRegistryVMWithRunner(
+                    "RMIRegistryRunner",
+                    " -Djava.rmi.server.useCodebaseOnly=false"
+                    + " -Duser.dir=" + rmiregistryDir.getAbsolutePath());
+            rmiregistry.start();
+            int port = rmiregistry.getPort();
+
+            File srcReadTest = new File(System.getProperty("test.classes", "."),
+                                    "RegistryLookup.class");
+            File destReadTest = new File(System.getProperty("user.dir", "."),
+                                    "RegistryLookup.class");
+            Files.move(srcReadTest.toPath(), destReadTest.toPath(),
+                                    StandardCopyOption.REPLACE_EXISTING);
+
+            File codebase = new File(System.getProperty("user.dir", "."));
+            client = new JavaVM("RegistryLookup",
+                    " -Djava.rmi.server.codebase=" + codebase.toURI().toURL()
+                    + " -cp ." + File.pathSeparator + System.getProperty("test.class.path"),
+                    Integer.toString(port));
+            int exit = client.execute();
+            if (exit == RegistryLookup.EXIT_FAIL) {
+                throw new RuntimeException("Test Fails");
+            }
+        } finally {
+            if (rmiregistry != null) {
+                rmiregistry.cleanup();
+            }
+            if (client != null) {
+                client.cleanup();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/RegistryLookup.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+public class RegistryLookup {
+    public static final int EXIT_FAIL = 1;
+
+    public static void main(String args[]) throws Exception {
+        Registry registry = null;
+        int exit = 0;
+        try {
+            int port = Integer.valueOf(args[0]);
+
+            testPkg.Server obj = new testPkg.Server();
+            testPkg.Hello stub =
+                    (testPkg.Hello) UnicastRemoteObject.exportObject(obj, 0);
+            // Bind the remote object's stub in the registry
+            registry = LocateRegistry.getRegistry(port);
+            registry.bind("Hello", stub);
+            System.err.println("Server ready");
+
+            testPkg.Client client = new testPkg.Client(port);
+            String testStubReturn = client.testStub();
+            if(!testStubReturn.equals(obj.hello)) {
+                throw new RuntimeException("Test Fails : "
+                        + "unexpected string from stub call");
+            }
+            registry.unbind("Hello");
+            System.out.println("Test passed");
+        } catch (Exception ex) {
+            exit = EXIT_FAIL;
+            ex.printStackTrace();
+        }
+        // need to exit explicitly, and parent process uses exit value
+        // to tell if the test passed.
+        System.exit(exit);
+    }
+}
--- a/jdk/test/java/rmi/registry/readTest/readTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.rmi.registry.Registry;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-
-public class readTest {
-
-    public static void main(String args[]) throws Exception {
-        try {
-            testPkg.Server obj = new testPkg.Server();
-            testPkg.Hello stub = (testPkg.Hello) UnicastRemoteObject.exportObject(obj, 0);
-            // Bind the remote object's stub in the registry
-            Registry registry =
-                LocateRegistry.getRegistry(TestLibrary.READTEST_REGISTRY_PORT);
-            registry.bind("Hello", stub);
-
-            System.err.println("Server ready");
-
-            // now, let's test client
-            testPkg.Client client =
-                new testPkg.Client(TestLibrary.READTEST_REGISTRY_PORT);
-            String testStubReturn = client.testStub();
-            if(!testStubReturn.equals(obj.hello)) {
-                throw new RuntimeException("Test Fails : unexpected string from stub call");
-            } else {
-                System.out.println("Test passed");
-            }
-            registry.unbind("Hello");
-
-        } catch (Exception e) {
-            System.err.println("Server exception: " + e.toString());
-            e.printStackTrace();
-        }
-
-    }
-}
--- a/jdk/test/java/rmi/registry/readTest/readTest.sh	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +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.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 7102369 7094468 7100592
-# @modules java.rmi/sun.rmi.registry
-#          java.rmi/sun.rmi.server
-#          java.rmi/sun.rmi.transport
-#          java.rmi/sun.rmi.transport.tcp
-# @library ../../testlibrary
-# @build TestLibrary
-# @summary remove java.rmi.server.codebase property parsing from registyimpl
-# @run shell readTest.sh
-# @key intermittent
-
-OS=`uname -s`
-VER=`uname -r`
-ARGS=""
-REGARGS=""
-
-case "$OS" in
-  SunOS | Linux | Darwin | AIX )
-    PS=":"
-    FS="/"
-    CHMOD="${FS}bin${FS}chmod"
-    FILEURL="file:"
-    ;;
-  Windows* )
-    PS=";"
-    FS="\\"
-    CHMOD="chmod"
-    FILEURL="file:/"
-    if [ "$VER" -eq "5" ]; then
-        ARGS="-Djdk.net.ephemeralPortRange.low=1024 -Djdk.net.ephemeralPortRange.high=65000"
-        REGARGS="-J-Djdk.net.ephemeralPortRange.low=1024 -J-Djdk.net.ephemeralPortRange.high=65000"
-    fi
-    ;;
-  CYGWIN* )
-    PS=";"
-    FS="/"
-    CHMOD="chmod"
-    FILEURL="file:/"
-    if [ "$VER" -eq "5" ]; then
-        ARGS="-Djdk.net.ephemeralPortRange.low=1024 -Djdk.net.ephemeralPortRange.high=65000"
-        REGARGS="-J-Djdk.net.ephemeralPortRange.low=1024 -J-Djdk.net.ephemeralPortRange.high=65000"
-    fi
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-TEST_CLASSPATH=.$PS${TESTCLASSPATH:-$TESTCLASSES}
-cp -r ${TESTSRC}${FS}* .
-${CHMOD} -R u+w *
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} testPkg${FS}*java
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -cp $TEST_CLASSPATH readTest.java
-
-mkdir rmi_tmp
-RMIREG_OUT=rmi.out
-#start rmiregistry without any local classes on classpath
-cd rmi_tmp
-# NOTE: This RMI Registry port must match TestLibrary.READTEST_REGISTRY_PORT
-${TESTJAVA}${FS}bin${FS}rmiregistry ${REGARGS} -J-Djava.rmi.server.useCodebaseOnly=false \
-    ${TESTTOOLVMOPTS} 60005 > ..${FS}${RMIREG_OUT} 2>&1 &
-RMIREG_PID=$!
-# allow some time to start
-sleep 3
-cd ..
-
-case "$OS" in
-  CYGWIN* )
-    CODEBASE=`cygpath -w $PWD`
-    ;;
-  * )
-    CODEBASE=`pwd`
-    ;;
-esac
-# trailing / after code base is important for rmi codebase property.
-TESTVMOPTS="${TESTVMOPTS} \
- --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED \
- --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED \
- --add-exports java.rmi/sun.rmi.transport=ALL-UNNAMED \
- --add-exports java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp $TEST_CLASSPATH ${ARGS} -Djava.rmi.server.codebase=${FILEURL}$CODEBASE/ readTest > OUT.TXT 2>&1 &
-TEST_PID=$!
-#bulk of testcase - let it run for a while
-sleep 5
-
-#we're done, kill processes first
-kill -9 ${RMIREG_PID} ${TEST_PID}
-sleep 3
-
-echo "Test output : "
-
-cat OUT.TXT
-echo "=============="
-echo "rmiregistry output  : "
-cat ${RMIREG_OUT}
-echo "=============="
-
-grep "Server ready" OUT.TXT
-result1=$?
-grep "Test passed" OUT.TXT
-result2=$?
-
-if [ $result1 -eq 0  -a $result2 -eq 0 ]
-then
-    echo "Passed"
-    exitCode=0;
-else
-    echo "Failed"
-    exitCode=1
-fi
-rm -rf OUT.TXT ${RMIREG_OUT} rmi_tmp
-exit ${exitCode}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/registry/readTest/registry.security.policy	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,12 @@
+grant {
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.registry";
+  permission java.util.PropertyPermission "env.class.path", "read";
+  permission java.io.FilePermission ".", "read";
+  permission java.util.PropertyPermission "user.dir", "read";
+  permission java.lang.RuntimePermission "createClassLoader";
+  permission java.lang.RuntimePermission "setContextClassLoader";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.transport.tcp";
+  permission java.net.SocketPermission "*:1024-", "listen,resolve,connect,accept";
+};
--- a/jdk/test/java/rmi/registry/reexport/Reexport.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/registry/reexport/Reexport.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary REGISTRY RegistryRunner
+ * @build TestLibrary RegistryVM RegistryRunner
  * @run main/othervm Reexport
  */
 
@@ -114,7 +114,7 @@
 
     public static void makeRegistry() {
         try {
-            subreg = REGISTRY.createREGISTRY();
+            subreg = RegistryVM.createRegistryVM();
             subreg.start();
             port = subreg.getPort();
             System.out.println("Starting registry on port " + port);
@@ -125,12 +125,12 @@
         }
     }
 
-    private static REGISTRY subreg = null;
+    private static RegistryVM subreg = null;
     private static int port = -1;
 
     public static void killRegistry() {
         if (subreg != null) {
-            subreg.shutdown();
+            subreg.cleanup();
             subreg = null;
         }
     }
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -230,6 +230,22 @@
     }
 
     /**
+     * Return exit value for vm process.
+     * @return exit value for vm process
+     * @throws IllegalThreadStateException if the vm process has not yet terminated
+     */
+    public int exitValue() {
+        return vm.exitValue();
+    }
+
+    /**
+     * Destroy the vm process, and do necessary cleanup.
+     */
+    public void cleanup() {
+        destroy();
+    }
+
+    /**
      * Destroys the VM, waits for it to terminate, and returns
      * its exit status.
      *
--- a/jdk/test/java/rmi/testlibrary/REGISTRY.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * Class to run and control rmiregistry in a sub-process.
- *
- * We can't kill a registry if we have too-close control
- * over it.  We must make it in a subprocess, and then kill the
- * subprocess when it has served our needs.
- */
-public class REGISTRY extends JavaVM {
-
-    private static final double START_TIMEOUT =
-            20_000 * TestLibrary.getTimeoutFactor();
-    private static final String DEFAULT_RUNNER = "RegistryRunner";
-
-    private int port = -1;
-
-    private REGISTRY(String runner, OutputStream out, OutputStream err,
-                    String options, int port) {
-        super(runner, options, Integer.toString(port), out, err);
-        try {
-            Class runnerClass = Class.forName(runner);
-            if (!RegistryRunner.class.isAssignableFrom(runnerClass)) {
-                throw new RuntimeException("runner class must be RegistryRunner"
-                        + " or its sub class");
-            }
-        } catch (ClassNotFoundException ex) {
-            throw new RuntimeException(ex);
-        }
-        this.port = port;
-    }
-
-    public static REGISTRY createREGISTRY() {
-        return createREGISTRYWithRunner(DEFAULT_RUNNER, System.out, System.err, "", 0);
-    }
-
-    public static REGISTRY createREGISTRY(OutputStream out, OutputStream err,
-                                    String options, int port) {
-        return createREGISTRYWithRunner(DEFAULT_RUNNER, out, err, options, port);
-    }
-
-    public static REGISTRY createREGISTRYWithRunner(String runner, String options) {
-        return createREGISTRYWithRunner(runner, System.out, System.err, options, 0);
-    }
-
-    public static REGISTRY createREGISTRYWithRunner(String runner, OutputStream out,
-                                        OutputStream err, String options, int port) {
-        options += " --add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED"
-                + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED"
-                + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED"
-                + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED";
-       REGISTRY reg = new REGISTRY(runner, out, err, options, port);
-       return reg;
-    }
-
-    /**
-     * Starts the registry in a sub-process and waits up to
-     * the given timeout period to confirm that it's running,
-     * and get the port where it's running.
-     */
-    public void start() throws IOException {
-        super.start();
-        long startTime = System.currentTimeMillis();
-        long deadline = TestLibrary.computeDeadline(startTime, (long)START_TIMEOUT);
-        while (true) {
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException ignore) { }
-
-            String output = outputStream.ba.toString();
-            port = RegistryRunner.getRegistryPort(output);
-            if (port != -1) {
-                break;
-            }
-            if (System.currentTimeMillis() > deadline) {
-                TestLibrary.bomb("Failed to start registry, giving up after " +
-                    (System.currentTimeMillis() - startTime) + "ms.", null);
-            }
-        }
-    }
-
-    /**
-     * Shuts down the registry.
-     */
-    public void shutdown() {
-        RegistryRunner.requestExit(port);
-    }
-
-    /**
-     * Gets the port where the registry is serving.
-     */
-    public int getPort() {
-        return port;
-    }
-}
--- a/jdk/test/java/rmi/testlibrary/RMID.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/testlibrary/RMID.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,18 +140,6 @@
     }
 
     private static String makeArgs(boolean includePortArg, int port) {
-        String propagateManager = null;
-
-        // rmid will run with a security manager set, but no policy
-        // file - it should not need one.
-        if (System.getSecurityManager() == null) {
-            propagateManager = MANAGER_OPTION +
-                TestParams.defaultSecurityManager;
-        } else {
-            propagateManager = MANAGER_OPTION +
-                System.getSecurityManager().getClass().getName();
-        }
-
         // getAbsolutePath requires permission to read user.dir
         String args =
             " -log " + (new File(LOGDIR, log)).getAbsolutePath();
@@ -210,7 +198,30 @@
                                   boolean debugExec, boolean includePortArg,
                                   int port)
     {
+        return createRMIDWithOptions(out, err, debugExec, includePortArg, port, "");
+    }
+
+    /**
+     * Create a RMID on a specified port capturing stdout and stderr
+     * with additional command line options and whether to print out
+     * debugging information that is used for spawning activation groups.
+     *
+     * @param out the OutputStream where the normal output of the
+     *            rmid subprocess goes
+     * @param err the OutputStream where the error output of the
+     *            rmid subprocess goes
+     * @param debugExec whether to print out debugging information
+     * @param includePortArg whether to include port argument
+     * @param port the port on which rmid accepts requests
+     * @param additionalOptions additional command line options
+     * @return a RMID instance
+     */
+    public static RMID createRMIDWithOptions(OutputStream out, OutputStream err,
+                                  boolean debugExec, boolean includePortArg,
+                                  int port, String additionalOptions)
+    {
         String options = makeOptions(port, debugExec, false);
+        options += " " + additionalOptions;
         String args = makeArgs(includePortArg, port);
         RMID rmid = new RMID("sun.rmi.server.Activation", options, args,
                              out, err, port);
@@ -223,6 +234,19 @@
         return createRMID(System.out, System.err, true, false, 0);
     }
 
+    /**
+     * Create a RMID on an ephemeral port capturing stdout and stderr
+     * with additional command line options.
+     *
+     * @param additionalOptions additional command line options
+     * @return a RMID instance
+     */
+    public static RMID createRMIDOnEphemeralPortWithOptions(
+                                            String additionalOptions) {
+        return createRMIDWithOptions(System.out, System.err,
+                                     true, false, 0, additionalOptions);
+    }
+
     public static RMID createRMIDOnEphemeralPort(OutputStream out,
                                                  OutputStream err,
                                                  boolean debugExec)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/testlibrary/RMIRegistryRunner.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**/
+
+import java.rmi.*;
+import java.rmi.registry.*;
+import java.rmi.server.*;
+
+/**
+ * Class to run a rmiregistry whose VM can be told to exit remotely;
+ * Difference between this class and RegistryRunner is that this class
+ * simulate rmiregistry closer than RegistryRunner.
+ */
+public class RMIRegistryRunner extends RegistryRunner
+{
+    public RMIRegistryRunner() throws RemoteException {
+    }
+
+    /**
+     * port 0 means to use ephemeral port to start registry.
+     *
+     * @param args command line arguments passed in from main
+     * @return the port number on which registry accepts requests
+     */
+    protected static int init(String[] args) {
+        try {
+            if (args.length == 0) {
+                System.err.println("Usage: <port>");
+                System.exit(0);
+            }
+            int port = -1;
+            port = Integer.parseInt(args[0]);
+
+            // call RegistryImpl.createRegistry to simulate rmiregistry.
+            registry = sun.rmi.registry.RegistryImpl.createRegistry(port);
+            if (port == 0) {
+                port = TestLibrary.getRegistryPort(registry);
+            }
+
+            // create a remote object to tell this VM to exit
+            exiter = new RMIRegistryRunner();
+            Naming.rebind("rmi://localhost:" + port +
+                          "/RemoteExiter", exiter);
+
+            return port;
+        } catch (Exception e) {
+            System.err.println(e.getMessage());
+            e.printStackTrace();
+            System.exit(1);
+        }
+        return -1;
+    }
+
+    public static void main(String[] args) {
+        int port = init(args);
+        notify(port);
+    }
+}
--- a/jdk/test/java/rmi/testlibrary/RegistryRunner.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/testlibrary/RegistryRunner.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
 
 /**
  * Class to run a registry whose VM can be told to exit remotely; using
- * the rmiregistry in this fashion makes tests more robust under
+ * a registry (in a sub-process) in this fashion makes tests more robust under
  * windows where Process.destroy() seems not to be 100% reliable.
  */
 public class RegistryRunner extends UnicastRemoteObject
@@ -38,8 +38,8 @@
     private static final String PORT_LABEL_START = "RegistryRunner.port.start:";
     private static final String PORT_LABEL_END = ":RegistryRunner.port.end";
 
-    private static Registry registry = null;
-    private static RemoteExiter exiter = null;
+    protected static Registry registry = null;
+    protected static RemoteExiter exiter = null;
 
     public RegistryRunner() throws RemoteException {
     }
@@ -72,6 +72,7 @@
             } catch (RemoteException re) {
             }
             e = null;
+
         } catch (java.net.MalformedURLException mfue) {
             // will not happen
         } catch (NotBoundException nbe) {
@@ -97,6 +98,9 @@
 
     /**
      * port 0 means to use ephemeral port to start registry.
+     *
+     * @param args command line arguments passed in from main
+     * @return the port number on which registry accepts requests
      */
     protected static int init(String[] args) {
         try {
@@ -128,13 +132,15 @@
     }
 
     /**
-     * REGISTRY.start() will filter the output of registry subprocess,
-     * when valid port is detected, REGISTRY.start() returns.
+     * RegistryVM.start() will filter the output of registry subprocess,
+     * when valid port is detected, RegistryVM.start() returns.
      * So, for subclass, it's important to call this method after registry
      * is initialized and necessary remote objects have been bound.
+     *
+     * @param port the port on which registry accepts requests
      */
     protected static void notify(int port) {
-        // this output is important for REGISTRY to get the port
+        // this output is important for RegistryVM to get the port
         // where rmiregistry is serving
         System.out.println(PORT_LABEL_START + port + PORT_LABEL_END);
         System.out.flush();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/testlibrary/RegistryVM.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * Class to run and control registry/rmiregistry in a sub-process.
+ * The behaviour changes when use different runner, currently
+ * there are 2 built-in runners, RegistryRunner and RMIRegistryRunner.
+ *
+ * We can't kill a registry if we have too-close control
+ * over it.  We must make it in a subprocess, and then kill the
+ * subprocess when it has served our needs.
+ */
+public class RegistryVM extends JavaVM {
+
+    private static final double START_TIMEOUT =
+            20_000 * TestLibrary.getTimeoutFactor();
+    private static final String DEFAULT_RUNNER = "RegistryRunner";
+
+    private int port = -1;
+
+    private RegistryVM(String runner, OutputStream out, OutputStream err,
+                    String options, int port) {
+        super(runner, options, Integer.toString(port), out, err);
+        try {
+            Class runnerClass = Class.forName(runner);
+            if (!RegistryRunner.class.isAssignableFrom(runnerClass)) {
+                throw new RuntimeException("runner class must be RegistryRunner"
+                        + " or its sub class");
+            }
+        } catch (ClassNotFoundException ex) {
+            throw new RuntimeException(ex);
+        }
+        this.port = port;
+    }
+
+    /**
+     * Create a RegistryVM instance on an ephemeral port.
+     *
+     * @return a RegistryVM instance
+     */
+    public static RegistryVM createRegistryVM() {
+        return createRegistryVMWithRunner(DEFAULT_RUNNER, System.out, System.err, "", 0);
+    }
+
+    /**
+     * Create a RegistryVM instance on an ephemeral port with additional
+     * command line options.
+     *
+     * @param options command line options
+     * @return a RegistryVM instance
+     */
+    public static RegistryVM createRegistryVM(String options) {
+        return createRegistryVMWithRunner(
+                DEFAULT_RUNNER, System.out, System.err, options, 0);
+    }
+
+    /**
+     * Create a RegistryVM instance on a specified port capturing stdout and
+     * stderr with additional command line options.
+     *
+     * @param out the OutputStream where the normal output of the
+     *            registry subprocess goes
+     * @param err the OutputStream where the error output of the
+     *            registry subprocess goes
+     * @param options the command line options
+     * @param port the port on which Registry accepts requests
+     * @return a RegistryVM instance
+     */
+    public static RegistryVM createRegistryVM(OutputStream out, OutputStream err,
+                                              String options, int port) {
+        return createRegistryVMWithRunner(DEFAULT_RUNNER, out, err, options, port);
+    }
+
+    /**
+     * Create a RegistryVM instance on an ephemeral port with additional
+     * command line options and a specified runner.
+     *
+     * @param runner the runner class name
+     * @param options command line options
+     * @return a RegistryVM instance
+     */
+    public static RegistryVM createRegistryVMWithRunner(String runner, String options) {
+        return createRegistryVMWithRunner(runner, System.out, System.err, options, 0);
+    }
+
+    /**
+     * Create a RegistryVM instance on a specified port capturing stdout and
+     * stderr with additional command line options and a specified runner.
+     *
+     * @param runner the runner class name
+     * @param out the OutputStream where the normal output of the
+     *            registry subprocess goes
+     * @param err the OutputStream where the error output of the
+     *            registry subprocess goes
+     * @param options the command line options
+     * @param port the port on which Registry accepts requests
+     * @return a RegistryVM instance
+     */
+    public static RegistryVM createRegistryVMWithRunner(String runner, OutputStream out,
+                                        OutputStream err, String options, int port) {
+        options += " --add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED"
+                + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED"
+                + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED"
+                + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED";
+        RegistryVM reg = new RegistryVM(runner, out, err, options, port);
+        reg.setPolicyFile(TestParams.defaultRegistryPolicy);
+        return reg;
+    }
+
+    /**
+     * Starts the registry in a sub-process and waits up to
+     * the given timeout period to confirm that it's running,
+     * and get the port where it's running.
+     *
+     * @throws IOException if fails to start subprocess
+     */
+    public void start() throws IOException {
+        super.start();
+        long startTime = System.currentTimeMillis();
+        long deadline = TestLibrary.computeDeadline(startTime, (long)START_TIMEOUT);
+        while (true) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ignore) { }
+
+            String output = outputStream.ba.toString();
+            port = RegistryRunner.getRegistryPort(output);
+            if (port != -1) {
+                break;
+            }
+            try {
+                int exit = vm.exitValue();
+                TestLibrary.bomb("[RegistryVM] registry sub-process exited with status "
+                        + exit + ".");
+            } catch (IllegalThreadStateException ignore) { }
+
+            if (System.currentTimeMillis() > deadline) {
+                TestLibrary.bomb("Failed to start registry, giving up after " +
+                    (System.currentTimeMillis() - startTime) + "ms.", null);
+            }
+        }
+    }
+
+    /**
+     * Shuts down the registry.
+     */
+    @Override
+    public void cleanup() {
+        RegistryRunner.requestExit(port);
+        super.destroy();
+    }
+
+    /**
+     * Gets the port where the registry is serving.
+     *
+     * @return the port where the registry is serving
+     */
+    public int getPort() {
+        return port;
+    }
+}
--- a/jdk/test/java/rmi/testlibrary/TestParams.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/testlibrary/TestParams.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,9 @@
     /** name of default security policy for RMID */
     public static final String defaultRmidPolicy;
 
+    /** name of default security policy for RegistryVM */
+    public static final String defaultRegistryPolicy;
+
     /** name of default security policy for activation groups */
     public static final String defaultGroupPolicy;
 
@@ -69,6 +72,9 @@
         defaultRmidPolicy =
             testSrc + File.separatorChar + "rmid.security.policy";
 
+        defaultRegistryPolicy =
+            testSrc + File.separatorChar + "registry.security.policy";
+
         defaultGroupPolicy =
             testSrc + File.separatorChar + "group.security.policy";
 
--- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary Test TestImpl REGISTRY RegistryRunner
+ * @build TestLibrary Test TestImpl RegistryVM RegistryRunner
  * @run main/othervm/policy=security.policy/timeout=360 DGCDeadLock
  */
 
@@ -68,21 +68,18 @@
 
     static public void main(String[] args) {
 
-        REGISTRY testImplVM = null;
+        RegistryVM testImplVM = null;
 
         System.err.println("\nregression test for 4118056\n");
         TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager");
 
         try {
-            String options = " -Djava.security.policy=" +
-                TestParams.defaultPolicy +
-                " --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" +
+            String options = " --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" +
                 " -Djava.rmi.dgc.leaseValue=500000" +
                 " -Dsun.rmi.dgc.checkInterval=" +
-                (HOLD_TARGET_TIME - 5000) +
-                "" ;
+                (HOLD_TARGET_TIME - 5000);
 
-            testImplVM = REGISTRY.createREGISTRYWithRunner("TestImpl", options);
+            testImplVM = RegistryVM.createRegistryVMWithRunner("TestImpl", options);
             testImplVM.start();
             registryPort = testImplVM.getPort();
 
@@ -107,7 +104,7 @@
             TestLibrary.bomb("test failed in main()", e);
         } finally {
             if (testImplVM != null) {
-                testImplVM.shutdown();
+                testImplVM.cleanup();
                 testImplVM = null;
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/registry.security.policy	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,27 @@
+/*
+ * security policy used by the registry sub-process
+ */
+
+grant {
+  // used by TestLibrary to determine extra commandline properties
+  permission java.io.FilePermission "..${/}..${/}test.props", "read";
+
+  // property specifically accessed by this test.
+  permission java.util.PropertyPermission "sun.rmi.transport.cleanInterval", "write";
+  permission java.util.PropertyPermission "package.restrict.access.sun", "read";
+  permission java.util.PropertyPermission "package.restrict.access.sun.rmi", "read";
+
+  // test needs to use java to exec an EchoImpl object
+  permission java.io.FilePermission "${java.home}${/}bin${/}java", "execute";
+
+  // used by TestLibrary to determine test environment 
+  permission java.util.PropertyPermission "test.*", "read";
+  permission java.util.PropertyPermission "user.dir", "read";
+  permission java.util.PropertyPermission "java.home", "read";
+
+  permission java.util.PropertyPermission "java.security.policy", "read";
+  permission java.util.PropertyPermission "java.security.manager", "read";
+
+  // test needs to export rmid and communicate with objects on arbitrary ports
+  permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+};
--- a/jdk/test/java/time/TEST.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/TEST.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -1,7 +1,6 @@
 # Threeten test uses TestNG
 TestNG.dirs = .
 othervm.dirs = tck/java/time/chrono test/java/time/chrono test/java/time/format
-modules = jdk.localedata
 lib.dirs = ../../lib/testlibrary
 lib.build = jdk.testlibrary.RandomFactory
 modules = java.base/java.time:open java.base/java.time.chrono:open java.base/java.time.zone:open
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java	Wed Jul 05 22:42:01 2017 +0200
@@ -880,25 +880,6 @@
     }
 
     //-----------------------------------------------------------------------
-    @DataProvider(name="patternPrint")
-    Object[][] data_patternPrint() {
-        return new Object[][] {
-            {"Q", date(2012, 2, 10), "1"},
-            {"QQ", date(2012, 2, 10), "01"},
-            {"QQQ", date(2012, 2, 10), "Q1"},
-            {"QQQQ", date(2012, 2, 10), "1st quarter"},
-            {"QQQQQ", date(2012, 2, 10), "1"},
-        };
-    }
-
-    @Test(dataProvider="patternPrint")
-    public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception {
-        DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK);
-        String test = f.format(temporal);
-        assertEquals(test, expected);
-    }
-
-    //-----------------------------------------------------------------------
     @DataProvider(name="localePatterns")
     Object[][] localizedDateTimePatterns() {
         return new Object[][] {
@@ -914,48 +895,6 @@
             {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"},
             {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a"},
             {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "h:mm a"},
-
-            // French Locale and ISO Chronology
-            {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"},
-            {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"},
-            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"},
-            {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"},
-            {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"},
-            {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"},
-            {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"},
-            {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"},
-            {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"},
-            {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"},
-            {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"},
-            {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"},
-
-            // Japanese Locale and JapaneseChronology
-            {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"},
-            {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"},
-            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"},
-            {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"},
-            {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
-            {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"},
-            {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"},
-            {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"},
-            {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"},
-            {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"},
-
-            // Chinese Local and Chronology
-            {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"},
-            {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"},
-            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"},
-            {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"},
-            {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
-            {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"},
-            {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"},
-            {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"},
-            {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"},
-            {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"},
         };
     }
 
@@ -1004,5 +943,4 @@
     private static Temporal date(int y, int m, int d) {
         return LocalDate.of(y, m, d);
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+package test.java.time.format;
+
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.MinguoChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.FormatStyle;
+import java.time.LocalDate;
+import java.time.temporal.Temporal;
+
+import java.util.Locale;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Test DateTimeFormatterBuilder.
+ */
+@Test
+public class TestDateTimeFormatterBuilderWithLocale {
+
+    private DateTimeFormatterBuilder builder;
+
+    @BeforeMethod
+    public void setUp() {
+        builder = new DateTimeFormatterBuilder();
+    }
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="patternPrint")
+    Object[][] data_patternPrint() {
+        return new Object[][] {
+            {"Q", date(2012, 2, 10), "1"},
+            {"QQ", date(2012, 2, 10), "01"},
+            {"QQQ", date(2012, 2, 10), "Q1"},
+            {"QQQQ", date(2012, 2, 10), "1st quarter"},
+            {"QQQQQ", date(2012, 2, 10), "1"},
+        };
+    }
+
+    @Test(dataProvider="patternPrint")
+    public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception {
+        DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK);
+        String test = f.format(temporal);
+        assertEquals(test, expected);
+    }
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="localePatterns")
+    Object[][] localizedDateTimePatterns() {
+        return new Object[][] {
+            // French Locale and ISO Chronology
+            {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"},
+            {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"},
+            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"},
+            {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"},
+            {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"},
+            {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"},
+            {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"},
+            {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"},
+            {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"},
+            {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"},
+            {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"},
+            {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"},
+
+            // Japanese Locale and JapaneseChronology
+            {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"},
+            {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"},
+            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"},
+            {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"},
+            {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
+            {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"},
+            {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"},
+            {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"},
+            {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"},
+            {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"},
+
+            // Chinese Local and Chronology
+            {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"},
+            {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"},
+            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"},
+            {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"},
+            {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
+            {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"},
+            {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"},
+            {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"},
+            {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"},
+            {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"},
+        };
+    }
+
+    @Test(dataProvider="localePatterns")
+    public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle,
+            Chronology chrono, Locale locale, String expected) {
+        String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale);
+        assertEquals(actual, expected, "Pattern " + convertNonAscii(actual));
+    }
+
+    /**
+     * Returns a string that includes non-ascii characters after expanding
+     * the non-ascii characters to their Java language \\uxxxx form.
+     * @param input an input string
+     * @return the encoded string.
+     */
+    private String convertNonAscii(String input) {
+        StringBuilder sb = new StringBuilder(input.length() * 6);
+        for (int i = 0; i < input.length(); i++) {
+            char ch = input.charAt(i);
+            if (ch < 255) {
+                sb.append(ch);
+            } else {
+                sb.append("\\u");
+                sb.append(Integer.toHexString(ch));
+            }
+        }
+        return sb.toString();
+    }
+
+    private static Temporal date(int y, int m, int d) {
+        return LocalDate.of(y, m, d);
+    }
+}
--- a/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProvider.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,6 @@
 public class TestDateTimeTextProvider extends AbstractTestPrinterParser {
 
     Locale enUS = new Locale("en", "US");
-    Locale ptBR = new Locale("pt", "BR");
 
     //-----------------------------------------------------------------------
     @DataProvider(name = "Text")
@@ -94,14 +93,6 @@
             {DAY_OF_WEEK, 6, TextStyle.SHORT, enUS, "Sat"},
             {DAY_OF_WEEK, 7, TextStyle.SHORT, enUS, "Sun"},
 
-            {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"},
-            {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"},
-            {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"},
-            {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"},
-            {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"},
-            {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"},
-            {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"},
-
             {DAY_OF_WEEK, 1, TextStyle.FULL, enUS, "Monday"},
             {DAY_OF_WEEK, 2, TextStyle.FULL, enUS, "Tuesday"},
             {DAY_OF_WEEK, 3, TextStyle.FULL, enUS, "Wednesday"},
@@ -110,14 +101,6 @@
             {DAY_OF_WEEK, 6, TextStyle.FULL, enUS, "Saturday"},
             {DAY_OF_WEEK, 7, TextStyle.FULL, enUS, "Sunday"},
 
-            {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"},
-            {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"},
-            {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"},
-            {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"},
-            {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"},
-            {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"},
-            {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"},
-
             {MONTH_OF_YEAR, 1, TextStyle.SHORT, enUS, "Jan"},
             {MONTH_OF_YEAR, 2, TextStyle.SHORT, enUS, "Feb"},
             {MONTH_OF_YEAR, 3, TextStyle.SHORT, enUS, "Mar"},
@@ -131,19 +114,6 @@
             {MONTH_OF_YEAR, 11, TextStyle.SHORT, enUS, "Nov"},
             {MONTH_OF_YEAR, 12, TextStyle.SHORT, enUS, "Dec"},
 
-            {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan"},
-            {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev"},
-            {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar"},
-            {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr"},
-            {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai"},
-            {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun"},
-            {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul"},
-            {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago"},
-            {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set"},
-            {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out"},
-            {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov"},
-            {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez"},
-
             {MONTH_OF_YEAR, 1, TextStyle.FULL, enUS, "January"},
             {MONTH_OF_YEAR, 2, TextStyle.FULL, enUS, "February"},
             {MONTH_OF_YEAR, 3, TextStyle.FULL, enUS, "March"},
@@ -157,19 +127,6 @@
             {MONTH_OF_YEAR, 11, TextStyle.FULL, enUS, "November"},
             {MONTH_OF_YEAR, 12, TextStyle.FULL, enUS, "December"},
 
-            {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"},
-            {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"},
-            {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"},
-            {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"},
-            {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"},
-            {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"},
-            {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"},
-            {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"},
-            {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"},
-            {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"},
-            {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"},
-            {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"},
-
             {AMPM_OF_DAY, 0, TextStyle.SHORT, enUS, "AM"},
             {AMPM_OF_DAY, 1, TextStyle.SHORT, enUS, "PM"},
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+
+package test.java.time.format;
+
+import static java.time.temporal.ChronoField.AMPM_OF_DAY;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static org.testng.Assert.assertEquals;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.TextStyle;
+import java.time.temporal.TemporalField;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Test SimpleDateTimeTextProviderWithLocale.
+ */
+@Test
+public class TestDateTimeTextProviderWithLocale extends AbstractTestPrinterParser {
+
+    Locale enUS = new Locale("en", "US");
+    Locale ptBR = new Locale("pt", "BR");
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name = "Text")
+    Object[][] data_text() {
+        return new Object[][] {
+            {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"},
+            {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"},
+            {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"},
+            {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"},
+            {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"},
+            {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"},
+            {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"},
+
+            {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"},
+            {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"},
+            {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"},
+            {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"},
+            {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"},
+            {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"},
+            {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"},
+
+            {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan"},
+            {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev"},
+            {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar"},
+            {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr"},
+            {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai"},
+            {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun"},
+            {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul"},
+            {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago"},
+            {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set"},
+            {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out"},
+            {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov"},
+            {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez"},
+
+            {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"},
+            {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"},
+            {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"},
+            {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"},
+            {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"},
+            {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"},
+            {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"},
+            {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"},
+            {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"},
+            {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"},
+            {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"},
+            {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"},
+
+        };
+    }
+
+    @Test(dataProvider = "Text")
+    public void test_getText(TemporalField field, Number value, TextStyle style, Locale locale, String expected) {
+          DateTimeFormatter fmt = getFormatter(field, style).withLocale(locale);
+          assertEquals(fmt.format(ZonedDateTime.now().with(field, value.longValue())), expected);
+    }
+
+}
--- a/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java	Wed Jul 05 22:42:01 2017 +0200
@@ -20,13 +20,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package test.java.time.format;
-
 /*
  * @test
+ * @modules jdk.localedata
  * @bug 8146750
  * @summary Test Narrow and NarrowStandalone month names are retrieved correctly.
  */
+package test.java.time.format;
+
 import static org.testng.Assert.assertEquals;
 
 import java.time.DayOfWeek;
--- a/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/test/java/time/format/TestNonIsoFormatter.java	Wed Jul 05 22:42:01 2017 +0200
@@ -20,6 +20,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+/*
+ *
+ * @test
+ * @modules jdk.localedata
+ */
+
 package test.java.time.format;
 
 import static org.testng.Assert.assertEquals;
--- a/jdk/test/java/time/test/java/time/format/TestTextParser.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/test/java/time/format/TestTextParser.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,16 +68,9 @@
 
 import java.text.ParsePosition;
 import java.time.DayOfWeek;
-import java.time.chrono.ChronoLocalDate;
-import java.time.chrono.JapaneseChronology;
-import java.time.chrono.HijrahDate;
-import java.time.chrono.JapaneseDate;
-import java.time.chrono.MinguoDate;
-import java.time.chrono.ThaiBuddhistDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.TextStyle;
-import java.time.format.SignStyle;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQueries;
@@ -92,8 +85,6 @@
  */
 @Test
 public class TestTextParser extends AbstractTestPrinterParser {
-    static final Locale RUSSIAN = new Locale("ru");
-    static final Locale FINNISH = new Locale("fi");
 
     //-----------------------------------------------------------------------
     @DataProvider(name="error")
@@ -213,20 +204,6 @@
        };
     }
 
-    // Test data is dependent on localized resources.
-    @DataProvider(name="parseStandaloneText")
-    Object[][] providerStandaloneText() {
-        // Locale, TemporalField, TextStyle, expected value, input text
-        return new Object[][] {
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,   1, "\u044f\u043d\u0432\u0430\u0440\u044c"},
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"},
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE,  1, "\u044f\u043d\u0432."},
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a."},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,   2, "tiistai"},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE,  2, "ti"},
-        };
-    }
-
     @DataProvider(name="parseDayOfWeekText")
     Object[][] providerDayOfWeekData() {
         return new Object[][] {
@@ -234,26 +211,9 @@
             {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
             {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
             {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
-
-            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
-            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
-            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
         };
     }
 
-    // Test data is dependent on localized resources.
-    @DataProvider(name="parseLenientText")
-    Object[][] providerLenientText() {
-        // Locale, TemporalField, expected value, input text
-        return new Object[][] {
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f"}, // full format
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, // full standalone
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short format
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short standalone
-        };
-    }
-
-
 
     @Test(dataProvider="parseText")
     public void test_parseText(TemporalField field, TextStyle style, int value, String input) throws Exception {
@@ -269,14 +229,6 @@
         assertEquals(pos.getIndex(), input.length());
     }
 
-    @Test(dataProvider="parseStandaloneText")
-    public void test_parseStandaloneText(Locale locale, TemporalField field, TextStyle style, int expectedValue, String input) {
-        DateTimeFormatter formatter = getFormatter(field, style).withLocale(locale);
-        ParsePosition pos = new ParsePosition(0);
-        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
-        assertEquals(pos.getIndex(), input.length());
-    }
-
     @Test(dataProvider="parseDayOfWeekText")
     public void test_parseDayOfWeekText(Locale locale, String pattern, String input, DayOfWeek expected) {
         DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale);
@@ -374,25 +326,6 @@
     }
 
     //-----------------------------------------------------------------------
-    public void test_parse_french_short_strict_full_noMatch() throws Exception {
-        setStrict(true);
-        ParsePosition pos = new ParsePosition(0);
-        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
-                                                    .parseUnresolved("janvier", pos);
-        assertEquals(pos.getErrorIndex(), 0);
-    }
-
-    public void test_parse_french_short_strict_short_match() throws Exception {
-        setStrict(true);
-        ParsePosition pos = new ParsePosition(0);
-        assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
-                                                                 .parseUnresolved("janv.", pos)
-                                                                 .getLong(MONTH_OF_YEAR),
-                     1L);
-        assertEquals(pos.getIndex(), 5);
-    }
-
-    //-----------------------------------------------------------------------
     public void test_parse_full_lenient_full_match() throws Exception {
         setStrict(false);
         ParsePosition pos = new ParsePosition(0);
@@ -436,51 +369,4 @@
         assertEquals(pos.getIndex(), 1);
     }
 
-    @Test(dataProvider="parseLenientText")
-    public void test_parseLenientText(Locale locale, TemporalField field, int expectedValue, String input) {
-        setStrict(false);
-        ParsePosition pos = new ParsePosition(0);
-        DateTimeFormatter formatter = getFormatter(field).withLocale(locale);
-        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
-        assertEquals(pos.getIndex(), input.length());
-    }
-
-    //-----------------------------------------------------------------------
-    @DataProvider(name="parseChronoLocalDate")
-    Object[][] provider_chronoLocalDate() {
-        return new Object[][] {
-            { HijrahDate.now() },
-            { JapaneseDate.now() },
-            { MinguoDate.now() },
-            { ThaiBuddhistDate.now() }};
-    }
-
-    private static final DateTimeFormatter fmt_chrono =
-        new DateTimeFormatterBuilder()
-            .optionalStart()
-            .appendChronologyId()
-            .appendLiteral(' ')
-            .optionalEnd()
-            .optionalStart()
-            .appendText(ChronoField.ERA, TextStyle.SHORT)
-            .appendLiteral(' ')
-            .optionalEnd()
-            .appendValue(ChronoField.YEAR_OF_ERA, 1, 9, SignStyle.NORMAL)
-            .appendLiteral('-')
-            .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER)
-            .appendLiteral('-')
-            .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER)
-            .toFormatter();
-
-    @Test(dataProvider="parseChronoLocalDate")
-    public void test_chronoLocalDate(ChronoLocalDate date) throws Exception {
-        System.out.printf(" %s, [fmt=%s]%n", date, fmt_chrono.format(date));
-        assertEquals(date, fmt_chrono.parse(fmt_chrono.format(date), ChronoLocalDate::from));
-
-        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("[GGG ]yyy-MM-dd")
-                                                 .withChronology(date.getChronology());
-        System.out.printf(" %s, [fmt=%s]%n", date.toString(), fmt.format(date));
-        assertEquals(date, fmt.parse(fmt.format(date), ChronoLocalDate::from));
-    }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/test/java/time/format/TestTextParserWithLocale.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+
+package test.java.time.format;
+
+import java.text.ParsePosition;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.HijrahDate;
+import java.time.chrono.JapaneseDate;
+import java.time.chrono.MinguoDate;
+import java.time.chrono.ThaiBuddhistDate;
+import java.time.DayOfWeek;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
+import java.time.format.SignStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalField;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Test TextPrinterParser.
+ */
+@Test
+public class TestTextParserWithLocale extends AbstractTestPrinterParser {
+    static final Locale RUSSIAN = new Locale("ru");
+    static final Locale FINNISH = new Locale("fi");
+
+    @DataProvider(name="parseDayOfWeekText")
+    Object[][] providerDayOfWeekData() {
+        return new Object[][] {
+            // Locale, pattern, input text, expected DayOfWeek
+            {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
+            {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
+            {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
+
+            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
+            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
+            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
+        };
+    }
+
+    @Test(dataProvider="parseDayOfWeekText")
+    public void test_parseDayOfWeekText(Locale locale, String pattern, String input, DayOfWeek expected) {
+        DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale);
+        ParsePosition pos = new ParsePosition(0);
+        assertEquals(DayOfWeek.from(formatter.parse(input, pos)), expected);
+        assertEquals(pos.getIndex(), input.length());
+    }
+
+    //--------------------------------------------------------------------
+    // Test data is dependent on localized resources.
+    @DataProvider(name="parseStandaloneText")
+    Object[][] providerStandaloneText() {
+        // Locale, TemporalField, TextStyle, expected value, input text
+        return new Object[][] {
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,   1, "\u044f\u043d\u0432\u0430\u0440\u044c"},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE,  1, "\u044f\u043d\u0432."},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a."},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,   2, "tiistai"},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE,  2, "ti"},
+        };
+    }
+
+    // Test data is dependent on localized resources.
+    @DataProvider(name="parseLenientText")
+    Object[][] providerLenientText() {
+        // Locale, TemporalField, expected value, input text
+        return new Object[][] {
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f"}, // full format
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, // full standalone
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short format
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short standalone
+        };
+    }
+
+    @Test(dataProvider="parseStandaloneText")
+    public void test_parseStandaloneText(Locale locale, TemporalField field, TextStyle style, int expectedValue, String input) {
+        DateTimeFormatter formatter = getFormatter(field, style).withLocale(locale);
+        ParsePosition pos = new ParsePosition(0);
+        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
+        assertEquals(pos.getIndex(), input.length());
+    }
+
+    //-----------------------------------------------------------------------
+    public void test_parse_french_short_strict_full_noMatch() throws Exception {
+        setStrict(true);
+        ParsePosition pos = new ParsePosition(0);
+        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
+                                                    .parseUnresolved("janvier", pos);
+        assertEquals(pos.getErrorIndex(), 0);
+    }
+
+    public void test_parse_french_short_strict_short_match() throws Exception {
+        setStrict(true);
+        ParsePosition pos = new ParsePosition(0);
+        assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
+                                                                 .parseUnresolved("janv.", pos)
+                                                                 .getLong(MONTH_OF_YEAR),
+                     1L);
+        assertEquals(pos.getIndex(), 5);
+    }
+
+    //-----------------------------------------------------------------------
+
+    @Test(dataProvider="parseLenientText")
+    public void test_parseLenientText(Locale locale, TemporalField field, int expectedValue, String input) {
+        setStrict(false);
+        ParsePosition pos = new ParsePosition(0);
+        DateTimeFormatter formatter = getFormatter(field).withLocale(locale);
+        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
+        assertEquals(pos.getIndex(), input.length());
+    }
+
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="parseChronoLocalDate")
+    Object[][] provider_chronoLocalDate() {
+        return new Object[][] {
+            { HijrahDate.now() },
+            { JapaneseDate.now() },
+            { MinguoDate.now() },
+            { ThaiBuddhistDate.now() }};
+    }
+
+    private static final DateTimeFormatter fmt_chrono =
+        new DateTimeFormatterBuilder()
+            .optionalStart()
+            .appendChronologyId()
+            .appendLiteral(' ')
+            .optionalEnd()
+            .optionalStart()
+            .appendText(ChronoField.ERA, TextStyle.SHORT)
+            .appendLiteral(' ')
+            .optionalEnd()
+            .appendValue(ChronoField.YEAR_OF_ERA, 1, 9, SignStyle.NORMAL)
+            .appendLiteral('-')
+            .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER)
+            .appendLiteral('-')
+            .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER)
+            .toFormatter();
+
+    @Test(dataProvider="parseChronoLocalDate")
+    public void test_chronoLocalDate(ChronoLocalDate date) throws Exception {
+        System.out.printf(" %s, [fmt=%s]%n", date, fmt_chrono.format(date));
+        assertEquals(date, fmt_chrono.parse(fmt_chrono.format(date), ChronoLocalDate::from));
+
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("[GGG ]yyy-MM-dd")
+                                                 .withChronology(date.getChronology());
+        System.out.printf(" %s, [fmt=%s]%n", date.toString(), fmt.format(date));
+        assertEquals(date, fmt.parse(fmt.format(date), ChronoLocalDate::from));
+    }
+}
--- a/jdk/test/java/time/test/java/time/format/TestTextPrinter.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/time/test/java/time/format/TestTextPrinter.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,8 +84,6 @@
  */
 @Test
 public class TestTextPrinter extends AbstractTestPrinterParser {
-    static final Locale RUSSIAN = new Locale("ru");
-    static final Locale FINNISH = new Locale("fi");
 
     //-----------------------------------------------------------------------
     @Test(expectedExceptions=DateTimeException.class)
@@ -213,32 +211,6 @@
             {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
             {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
             {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
-
-            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
-            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
-            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
-        };
-    }
-
-    @DataProvider(name="print_JapaneseChronology")
-    Object[][] provider_japaneseEra() {
-       return new Object[][] {
-            {ERA,           TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names.
-            {ERA,           TextStyle.SHORT, 2, "Heisei"},
-            {ERA,           TextStyle.NARROW, 2, "H"},
-       };
-    };
-
-    // Test data is dependent on localized resources.
-    @DataProvider(name="print_standalone")
-    Object[][] provider_StandaloneNames() {
-        return new Object[][] {
-            // standalone names for 2013-01-01 (Tue)
-            // Locale, TemporalField, TextStyle, expected text
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  "\u044f\u043d\u0432\u0430\u0440\u044c"},
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,  "tiistai"},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE, "ti"},
         };
     }
 
@@ -255,30 +227,6 @@
         assertEquals(text, expected);
     }
 
-    @Test(dataProvider="print_JapaneseChronology")
-    public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception {
-        LocalDate ld = LocalDate.of(2013, 1, 31);
-        getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf);
-        assertEquals(buf.toString(), expected);
-    }
-
-    @Test(dataProvider="print_standalone")
-    public void test_standaloneNames(Locale locale, TemporalField field, TextStyle style, String expected) {
-        getFormatter(field, style).withLocale(locale).formatTo(LocalDate.of(2013, 1, 1), buf);
-        assertEquals(buf.toString(), expected);
-    }
-
-    //-----------------------------------------------------------------------
-    public void test_print_french_long() throws Exception {
-        getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
-        assertEquals(buf.toString(), "janvier");
-    }
-
-    public void test_print_french_short() throws Exception {
-        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
-        assertEquals(buf.toString(), "janv.");
-    }
-
     //-----------------------------------------------------------------------
     public void test_toString1() throws Exception {
         assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).toString(), "Text(MonthOfYear)");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+
+package test.java.time.format;
+
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.ERA;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.IsoFields.QUARTER_OF_YEAR;
+import static org.testng.Assert.assertEquals;
+
+import java.time.DateTimeException;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.chrono.JapaneseChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.TextStyle;
+import java.time.temporal.TemporalField;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import test.java.time.temporal.MockFieldValue;
+
+/**
+ * Test TextPrinterParserWithLocale.
+ */
+@Test
+public class TestTextPrinterWithLocale extends AbstractTestPrinterParser {
+    static final Locale RUSSIAN = new Locale("ru");
+    static final Locale FINNISH = new Locale("fi");
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="print_DayOfWeekData")
+    Object[][] providerDayOfWeekData() {
+        return new Object[][] {
+            // Locale, pattern, expected text, input DayOfWeek
+            {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
+            {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
+            {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
+
+            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
+            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
+            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
+        };
+    }
+
+    // Test data is dependent on localized resources.
+    @DataProvider(name="print_standalone")
+    Object[][] provider_StandaloneNames() {
+        return new Object[][] {
+            // standalone names for 2013-01-01 (Tue)
+            // Locale, TemporalField, TextStyle, expected text
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  "\u044f\u043d\u0432\u0430\u0440\u044c"},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,  "tiistai"},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE, "ti"},
+        };
+    }
+
+    @Test(dataProvider="print_DayOfWeekData")
+    public void test_formatDayOfWeek(Locale locale, String pattern, String expected, DayOfWeek dayOfWeek) {
+        DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale);
+        String text = formatter.format(dayOfWeek);
+        assertEquals(text, expected);
+    }
+
+    @Test(dataProvider="print_standalone")
+    public void test_standaloneNames(Locale locale, TemporalField field, TextStyle style, String expected) {
+        getFormatter(field, style).withLocale(locale).formatTo(LocalDate.of(2013, 1, 1), buf);
+        assertEquals(buf.toString(), expected);
+    }
+
+    //-----------------------------------------------------------------------
+    public void test_print_french_long() throws Exception {
+        getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
+        assertEquals(buf.toString(), "janvier");
+    }
+
+    public void test_print_french_short() throws Exception {
+        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
+        assertEquals(buf.toString(), "janv.");
+    }
+
+    @DataProvider(name="print_JapaneseChronology")
+    Object[][] provider_japaneseEra() {
+       return new Object[][] {
+            {ERA,           TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names.
+            {ERA,           TextStyle.SHORT, 2, "Heisei"},
+            {ERA,           TextStyle.NARROW, 2, "H"},
+       };
+    };
+
+    @Test(dataProvider="print_JapaneseChronology")
+    public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception {
+        LocalDate ld = LocalDate.of(2013, 1, 31);
+        getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf);
+        assertEquals(buf.toString(), expected);
+    }
+}
--- a/jdk/test/java/util/Collection/SetFactories.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/util/Collection/SetFactories.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,8 @@
               hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i")),
             a(   Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
               hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
+            a(   Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
+                 Set.of("j", "i", "h", "g", "f", "e", "d", "c", "b", "a")),
             a(   Set.of(stringArray),
               hashSetOf(stringArray))
         ).iterator();
@@ -183,6 +185,17 @@
         Set<String> set = Set.of(array);
     }
 
+    @Test(dataProvider="all")
+    public void hashCodeEqual(Set<String> act, Set<String> exp) {
+        assertEquals(act.hashCode(), exp.hashCode());
+    }
+
+    @Test(dataProvider="all")
+    public void containsAll(Set<String> act, Set<String> exp) {
+        assertTrue(act.containsAll(exp));
+        assertTrue(exp.containsAll(act));
+    }
+
     @Test(expectedExceptions=NullPointerException.class)
     public void nullDisallowed1() {
         Set.of((String)null); // force one-arg overload
--- a/jdk/test/java/util/Map/MapFactories.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/java/util/Map/MapFactories.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,8 @@
             a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h"), genMap(8)),
             a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i"), genMap(9)),
             a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), genMap(10)),
+            a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"),
+              Map.of(4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j", 0, "a", 1, "b", 2, "c", 3, "d")),
             a(Map.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES))
         ).iterator();
     }
@@ -135,6 +137,18 @@
         assertEquals(act, exp);
     }
 
+    @Test(dataProvider="all")
+    public void containsAllKeys(Map<Integer,String> act, Map<Integer,String> exp) {
+        assertTrue(act.keySet().containsAll(exp.keySet()));
+        assertTrue(exp.keySet().containsAll(act.keySet()));
+    }
+
+    @Test(dataProvider="all")
+    public void containsAllValues(Map<Integer,String> act, Map<Integer,String> exp) {
+        assertTrue(act.values().containsAll(exp.values()));
+        assertTrue(exp.values().containsAll(act.values()));
+    }
+
     @Test(expectedExceptions=IllegalArgumentException.class)
     public void dupKeysDisallowed2() {
         Map<Integer, String> map = Map.of(0, "a", 0, "b");
@@ -192,6 +206,11 @@
         Map<Integer, String> map = Map.ofEntries(entries);
     }
 
+    @Test(dataProvider="all")
+    public void hashCodeEquals(Map<Integer,String> act, Map<Integer,String> exp) {
+        assertEquals(act.hashCode(), exp.hashCode());
+    }
+
     @Test(expectedExceptions=NullPointerException.class)
     public void nullKeyDisallowed1() {
         Map<Integer, String> map = Map.of(null, "a");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/8133919/DrawGridLinesTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableModel;
+
+/*
+ * @test
+ * @bug 8133919
+ * @summary [macosx] JTable grid lines are incorrectly positioned on HiDPI display
+ * @run main DrawGridLinesTest
+ */
+public class DrawGridLinesTest {
+
+    private static final int WIDTH = 300;
+    private static final int HEIGHT = 150;
+    private static final Color GRID_COLOR = Color.BLACK;
+    private static final Color TABLE_BACKGROUND_COLOR = Color.BLUE;
+    private static final Color CELL_RENDERER_BACKGROUND_COLOR = Color.YELLOW;
+    private static final int SCALE = 2;
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(DrawGridLinesTest::checkTableGridLines);
+    }
+
+    private static void checkTableGridLines() {
+
+        TableModel dataModel = new AbstractTableModel() {
+            public int getColumnCount() {
+                return 10;
+            }
+
+            public int getRowCount() {
+                return 10;
+            }
+
+            public Object getValueAt(int row, int col) {
+                return " ";
+            }
+        };
+
+        DefaultTableCellRenderer r = new DefaultTableCellRenderer();
+        r.setOpaque(true);
+        r.setBackground(CELL_RENDERER_BACKGROUND_COLOR);
+
+        JTable table = new JTable(dataModel);
+        table.setSize(WIDTH, HEIGHT);
+        table.setDefaultRenderer(Object.class, r);
+        table.setGridColor(GRID_COLOR);
+        table.setShowGrid(true);
+        table.setShowHorizontalLines(true);
+        table.setShowVerticalLines(true);
+        table.setBackground(TABLE_BACKGROUND_COLOR);
+
+        checkTableGridLines(table);
+    }
+
+    private static void checkTableGridLines(JTable table) {
+
+        int w = SCALE * WIDTH;
+        int h = SCALE * HEIGHT;
+
+        BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g = img.createGraphics();
+        g.scale(SCALE, SCALE);
+        table.paint(g);
+        g.dispose();
+
+        int size = Math.min(w, h);
+        int rgb = TABLE_BACKGROUND_COLOR.getRGB();
+
+        for (int i = 0; i < size; i++) {
+            if (img.getRGB(i, i) == rgb || img.getRGB(i, size - i - 1) == rgb) {
+                throw new RuntimeException("Artifacts in the table background color!");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/PrintManualTest_FitWidthMultiple.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8170349
+ * @summary  Verify if printed content is within border and all columns are
+ *           printed for PrintMode.FIT_WIDTH
+ * @run main/manual PrintManualTest_FitWidthMultiple
+ */
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.text.MessageFormat;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+
+public class PrintManualTest_FitWidthMultiple extends JTable implements Runnable {
+
+    static boolean testPassed;
+    static JFrame fr = null;
+    static JFrame instructFrame = null;
+    private final CountDownLatch latch;
+
+    public PrintManualTest_FitWidthMultiple(CountDownLatch latch){
+        this.latch = latch;
+    }
+
+    @Override
+    public void run() {
+        try {
+            createUIandTest();
+        } catch (Exception ex) {
+            dispose();
+            latch.countDown();
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+
+    private void createUIandTest() throws Exception {
+        /*Message Format Header and Footer */
+        final MessageFormat header=new MessageFormat("JTable Printing Header {0}");
+        final MessageFormat footer = new MessageFormat("JTable Printing Footer {0}");
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                /* Instructions Section */
+                String info =
+                    " \nThis test case brings up JTable with more Columns and Rows \n"+
+                    "Press the Print Button. It Prints in PRINT_MODE_FIT_WIDTH \n" +
+                    "It Pops up the Print Dialog. Check if Job/Print Attributes in the\n" +
+                    "Print Dialog are configurable. Default Print out will be in Landscape \n"+
+                    "The Print out should have JTable Centered on the Print out with thin borders \n"+
+                    "Prints out with Header and Footer. \n"+
+                    "The JTable should have all columns printed within border";
+
+                instructFrame=new JFrame("PrintManualTest_NormalSingle");
+                JPanel panel=new JPanel(new BorderLayout());
+                JButton button1 = new JButton("Pass");
+                JButton button2 = new JButton("Fail");
+                button1.addActionListener((e) -> {
+                    testPassed = true;
+                    dispose();
+                    latch.countDown();
+                });
+                button2.addActionListener((e) -> {
+                    testPassed = false;
+                    dispose();
+                    latch.countDown();
+                });
+                JPanel btnpanel1 = new JPanel();
+                btnpanel1.add(button1);
+                btnpanel1.add(button2);
+                panel.add(addInfo(info),BorderLayout.CENTER);
+                panel.add(btnpanel1, BorderLayout.SOUTH);
+                instructFrame.getContentPane().add(panel);
+                instructFrame.setBounds(600,100,350,350);
+
+                /* Print Button */
+                final JButton printButton=new JButton("Print");
+
+                /* Table Model */
+                final TableModel datamodel=new AbstractTableModel(){
+                    @Override
+                    public int getColumnCount() { return 50;}
+                    @Override
+                    public int getRowCount() { return 50; }
+                    @Override
+                    public Object getValueAt(int row, int column){ return new Integer(row*column);}
+                };
+
+                /* Constructing the JTable */
+                final JTable table=new JTable(datamodel);
+
+                /* Putting the JTable in ScrollPane and Frame Container */
+                JScrollPane scrollpane=new JScrollPane(table);
+                fr = new JFrame("PrintManualTest_FitWidthMultiple");
+                fr.getContentPane().add(scrollpane);
+
+                /* Light Weight Panel for holding Print and other buttons */
+                JPanel btnpanel=new JPanel();
+                btnpanel.add(printButton);
+                fr.getContentPane().add(btnpanel,BorderLayout.SOUTH);
+                fr.setBounds(0,0,400,400);
+                fr.setSize(500,500);
+
+                /* Binding the KeyStroke to Print Button Action */
+                fr.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl P"), "printButton");
+                fr.getRootPane().getActionMap().put("printButton", new AbstractAction(){
+                    @Override
+                    public void actionPerformed(ActionEvent e){
+                        printButton.doClick();
+                    }
+                });
+
+                /* Container and Component Listeners */
+                fr.addWindowListener(new WindowAdapter() {
+                    @Override
+                    public void windowClosing(WindowEvent e) {
+                        dispose();
+                        if (testPassed == false) {
+                            throw new RuntimeException(" User has not executed the test");
+                        }
+                    }
+                });
+
+                final PrintRequestAttributeSet prattr=new HashPrintRequestAttributeSet();
+                prattr.add(javax.print.attribute.standard.OrientationRequested.LANDSCAPE);
+
+                printButton.addActionListener(new ActionListener(){
+                    @Override
+                    public void actionPerformed(ActionEvent ae){
+                        try{
+                            table.print(JTable.PrintMode.FIT_WIDTH, header,footer,true,prattr,true);
+                        } catch(Exception e){}
+                    }
+                });
+                instructFrame.setVisible(true);
+                fr.setVisible(true);
+            }
+        });
+    }
+
+    public void dispose() {
+        instructFrame.dispose();
+        fr.dispose();
+    }
+
+    public JScrollPane addInfo(String info) {
+        JTextArea jta = new JTextArea(info,8,20);
+        jta.setEditable(false);
+        jta.setLineWrap(true);
+        JScrollPane sp = new JScrollPane(jta);
+        return sp;
+
+    }
+
+    /* Main Method */
+
+    public static void main(String[] argv) throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        PrintManualTest_FitWidthMultiple test = new PrintManualTest_FitWidthMultiple(latch);
+        Thread T1 = new Thread(test);
+        T1.start();
+
+        // wait for latch to complete
+        boolean ret = false;
+        try {
+            ret = latch.await(60, TimeUnit.SECONDS);
+        } catch (InterruptedException ie) {
+            throw ie;
+        }
+        if (!ret) {
+            test.dispose();
+            throw new RuntimeException(" User has not executed the test");
+        }
+        if (test.testPassed == false) {
+            throw new RuntimeException("printed contents is beyond borders");
+        }
+    }
+}
--- a/jdk/test/javax/swing/text/View/8156217/FPMethodCalledTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/javax/swing/text/View/8156217/FPMethodCalledTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -42,7 +42,7 @@
 
 /**
  * @test
- * @bug 8156217
+ * @bug 8156217 8169922
  * @key headful
  * @summary Selected text is shifted on HiDPI display
  * @run main FPMethodCalledTest
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/ws/8159058/SaajEmptyNamespaceTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8159058
+ * @summary Test that empty default namespace declaration clears the
+ *          default namespace value
+ * @modules java.xml.ws/com.sun.xml.internal.ws.api
+ *          java.xml.ws/com.sun.xml.internal.ws.api.message.saaj
+ *          java.xml.ws/com.sun.xml.internal.ws.message.stream
+ * @run testng/othervm SaajEmptyNamespaceTest
+ */
+
+import com.sun.xml.internal.ws.api.SOAPVersion;
+import com.sun.xml.internal.ws.api.message.saaj.SAAJFactory;
+import com.sun.xml.internal.ws.message.stream.StreamMessage;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import javax.xml.namespace.QName;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.w3c.dom.Node;
+
+public class SaajEmptyNamespaceTest {
+
+    /*
+     * Test that SOAP message with default namespace declaration that contains empty
+     * string is properly processed by SAAJ reader.
+     */
+    @Test
+    public void testResetDefaultNamespaceSAAJ() throws Exception {
+        // Create SOAP message from XML string and process it with SAAJ reader
+        XMLStreamReader envelope = XMLInputFactory.newFactory().createXMLStreamReader(
+                new StringReader(INPUT_SOAP_MESSAGE));
+        StreamMessage streamMessage = new StreamMessage(SOAPVersion.SOAP_11,
+                envelope, null);
+        SAAJFactory saajFact = new SAAJFactory();
+        SOAPMessage soapMessage = saajFact.readAsSOAPMessage(SOAPVersion.SOAP_11, streamMessage);
+
+        // Check if constructed object model meets local names and namespace expectations
+        SOAPElement request = (SOAPElement) soapMessage.getSOAPBody().getFirstChild();
+        // Check top body element name
+        Assert.assertEquals(request.getLocalName(), "SampleServiceRequest");
+        // Check top body element namespace
+        Assert.assertEquals(request.getNamespaceURI(), TEST_NS);
+        SOAPElement params = (SOAPElement) request.getFirstChild();
+        // Check first child name
+        Assert.assertEquals(params.getLocalName(), "RequestParams");
+        // Check if first child namespace is null
+        Assert.assertNull(params.getNamespaceURI());
+
+        // Check inner elements of the first child
+        SOAPElement param1 = (SOAPElement) params.getFirstChild();
+        Assert.assertEquals(param1.getLocalName(), "Param1");
+        Assert.assertNull(param1.getNamespaceURI());
+        SOAPElement param2 = (SOAPElement) params.getChildNodes().item(1);
+        Assert.assertEquals(param2.getLocalName(), "Param2");
+        Assert.assertNull(param2.getNamespaceURI());
+        // Check full content of SOAP body
+        Assert.assertEquals(nodeToText(request), EXPECTED_RESULT);
+    }
+
+    /*
+     * Test that adding element with explicitly null namespace URI shall put the
+     * element into global namespace. Namespace declarations are not added explicitly.
+     */
+    @Test
+    public void testAddElementToNullNsNoDeclarations() throws Exception {
+        // Create empty SOAP message
+        SOAPMessage msg = createSoapMessage();
+        SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
+
+        // Add elements
+        SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS);
+        SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", null);
+        SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child");
+
+        // Check namespace URIs
+        Assert.assertNull(childGlobalNS.getNamespaceURI());
+        Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS);
+    }
+
+    /*
+     * Test that adding element with explicitly empty namespace URI shall put
+     * the element into global namespace. Namespace declarations are not added
+     * explicitly.
+     */
+    @Test
+    public void testAddElementToGlobalNsNoDeclarations() throws Exception {
+        // Create empty SOAP message
+        SOAPMessage msg = createSoapMessage();
+        SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
+
+        // Add elements
+        SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS);
+        SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", "");
+        SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child");
+
+        // Check namespace URIs
+        Assert.assertNull(childGlobalNS.getNamespaceURI());
+        Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS);
+    }
+
+    /*
+     * Test that adding element with explicitly empty namespace URI set via QName
+     * shall put the element into global namespace.
+     */
+    @Test
+    public void testAddElementToNullNsQName() throws Exception {
+        // Create empty SOAP message
+        SOAPMessage msg = createSoapMessage();
+        SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
+
+        // Add elements
+        SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS);
+        parentExplicitNS.addNamespaceDeclaration("", TEST_NS);
+        SOAPElement childGlobalNS = parentExplicitNS.addChildElement(new QName(null, "global-child"));
+        childGlobalNS.addNamespaceDeclaration("", "");
+        SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child");
+        SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child");
+
+        // Check namespace URIs
+        Assert.assertNull(childGlobalNS.getNamespaceURI());
+        Assert.assertNull(grandChildGlobalNS.getNamespaceURI());
+        Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS);
+    }
+
+    /*
+     * Test that adding element with explicitly empty namespace URI shall put
+     * the element into global namespace.
+     */
+    @Test
+    public void testAddElementToGlobalNs() throws Exception {
+        // Create empty SOAP message
+        SOAPMessage msg = createSoapMessage();
+        SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
+
+        // Add elements
+        SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS);
+        parentExplicitNS.addNamespaceDeclaration("", TEST_NS);
+        SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", "");
+        childGlobalNS.addNamespaceDeclaration("", "");
+        SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child");
+        SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child");
+
+        // Check namespace URIs
+        Assert.assertNull(childGlobalNS.getNamespaceURI());
+        Assert.assertNull(grandChildGlobalNS.getNamespaceURI());
+        Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS);
+    }
+
+    /*
+     * Test that adding element with explicitly null namespace URI shall put
+     * the element into global namespace.
+     */
+    @Test
+    public void testAddElementToNullNs() throws Exception {
+        // Create empty SOAP message
+        SOAPMessage msg = createSoapMessage();
+        SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
+
+        // Add elements
+        SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS);
+        parentExplicitNS.addNamespaceDeclaration("", TEST_NS);
+        SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", null);
+        childGlobalNS.addNamespaceDeclaration("", null);
+        SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child");
+        SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child");
+
+        // Check namespace URIs
+        Assert.assertNull(childGlobalNS.getNamespaceURI());
+        Assert.assertNull(grandChildGlobalNS.getNamespaceURI());
+        Assert.assertEquals(TEST_NS, childDefaultNS.getNamespaceURI());
+    }
+
+    /*
+     * Test that adding element with explicitly empty namespace URI via QName
+     * shall put the element in global namespace.
+     */
+    @Test
+    public void testAddElementToGlobalNsQName() throws Exception {
+        // Create empty SOAP message
+        SOAPMessage msg = createSoapMessage();
+        SOAPBody body = msg.getSOAPPart().getEnvelope().getBody();
+
+        // Add elements
+        SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS);
+        parentExplicitNS.addNamespaceDeclaration("", TEST_NS);
+        SOAPElement childGlobalNS = parentExplicitNS.addChildElement(new QName("", "global-child"));
+        childGlobalNS.addNamespaceDeclaration("", "");
+        SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child");
+        SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child");
+
+        // Check namespace URIs
+        Assert.assertNull(childGlobalNS.getNamespaceURI());
+        Assert.assertNull(grandChildGlobalNS.getNamespaceURI());
+        Assert.assertEquals(childDefaultNS.getNamespaceURI(),TEST_NS);
+    }
+
+    // Convert DOM node to text representation
+    private String nodeToText(Node node) throws TransformerException {
+        Transformer trans = TransformerFactory.newInstance().newTransformer();
+        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+        StringWriter writer = new StringWriter();
+        StreamResult result = new StreamResult(writer);
+        trans.transform(new DOMSource(node), result);
+        String bodyContent = writer.toString();
+        System.out.println("SOAP body content read by SAAJ:"+bodyContent);
+        return bodyContent;
+    }
+
+    // Create SOAP message with empty body
+    private static SOAPMessage createSoapMessage() throws SOAPException, UnsupportedEncodingException {
+        String xml = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+                    +"<SOAP-ENV:Body/></SOAP-ENV:Envelope>";
+        MessageFactory mFactory = MessageFactory.newInstance();
+        SOAPMessage msg = mFactory.createMessage();
+        msg.getSOAPPart().setContent(new StreamSource(new ByteArrayInputStream(xml.getBytes("utf-8"))));
+        return msg;
+    }
+
+    // Namespace value used in tests
+    private static String TEST_NS = "http://example.org/test";
+
+    // Content of SOAP message passed to SAAJ factory
+    private static String INPUT_SOAP_MESSAGE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+            + "<s:Body>"
+            + "<SampleServiceRequest xmlns=\"http://example.org/test\""
+            + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "<RequestParams xmlns=\"\">"
+            + "<Param1>hogehoge</Param1>"
+            + "<Param2>fugafuga</Param2>"
+            + "</RequestParams>"
+            + "</SampleServiceRequest>"
+            + "</s:Body>"
+            + "</s:Envelope>";
+
+    // Expected body content after SAAJ processing
+    private static String EXPECTED_RESULT = "<SampleServiceRequest"
+            +" xmlns=\"http://example.org/test\">"
+            + "<RequestParams xmlns=\"\">"
+            + "<Param1>hogehoge</Param1>"
+            + "<Param2>fugafuga</Param2>"
+            + "</RequestParams>"
+            + "</SampleServiceRequest>";
+}
--- a/jdk/test/lib/security/SecurityTools.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import jdk.testlibrary.JDKToolLauncher;
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-public class SecurityTools {
-
-    public static final String NO_ALIAS = null;
-
-    // keytool
-
-    public static OutputAnalyzer keytool(List<String> options)
-            throws Throwable {
-
-        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("keytool")
-                .addVMArg("-Duser.language=en")
-                .addVMArg("-Duser.country=US");
-        for (String option : options) {
-            if (option.startsWith("-J")) {
-                launcher.addVMArg(option.substring(2));
-            } else {
-                launcher.addToolArg(option);
-            }
-        }
-        return ProcessTools.executeCommand(launcher.getCommand());
-    }
-
-    public static OutputAnalyzer keytool(String options) throws Throwable {
-        return keytool(options.split("\\s+"));
-    }
-
-    public static OutputAnalyzer keytool(String... options) throws Throwable {
-        return keytool(List.of(options));
-    }
-
-    // jarsigner
-
-    public static OutputAnalyzer jarsigner(String jar, String alias,
-            List<String> options) throws Throwable {
-        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
-                .addVMArg("-Duser.language=en")
-                .addVMArg("-Duser.country=US");
-        for (String option : options) {
-            if (option.startsWith("-J")) {
-                launcher.addVMArg(option.substring(2));
-            } else {
-                launcher.addToolArg(option);
-            }
-        }
-        launcher.addToolArg(jar);
-        if (alias != null) {
-            launcher.addToolArg(alias);
-        }
-        return ProcessTools.executeCommand(launcher.getCommand());
-    }
-
-    public static OutputAnalyzer jarsigner(String jar, String alias,
-            String options) throws Throwable {
-
-        return jarsigner(jar, alias, options.split("\\s+"));
-    }
-
-    public static OutputAnalyzer jarsigner(String jar, String alias,
-            String... options) throws Throwable {
-
-        return jarsigner(jar, alias, List.of(options));
-    }
-
-    public static OutputAnalyzer sign(String jar, String alias, String... options)
-            throws Throwable {
-
-        return jarsigner(jar, alias,
-                mergeOptions("-J-Djava.security.egd=file:/dev/./urandom", options));
-    }
-
-    public static OutputAnalyzer verify(String jar, String... options)
-            throws Throwable {
-
-        return jarsigner(jar, NO_ALIAS, mergeOptions("-verify", options));
-    }
-
-    // helper methods
-
-    private static List<String> mergeOptions(
-            String firstOption, String... secondPart) {
-
-        return mergeOptions(List.of(firstOption), secondPart);
-    }
-
-    private static List<String> mergeOptions(
-            List<String> firstPart, String... secondPart) {
-
-        List<String> options = new ArrayList<>(firstPart);
-        Collections.addAll(options, secondPart);
-        return options;
-    }
-}
--- a/jdk/test/sun/net/www/protocol/http/SetIfModifiedSince.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/net/www/protocol/http/SetIfModifiedSince.java	Wed Jul 05 22:42:01 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 4213164
+   @bug 4213164 8172253
    @summary setIfModifiedSince mehtod in HttpURLConnection sometimes fails
    */
 import java.util.*;
@@ -88,7 +88,7 @@
      //url = new URL(args[0]);
      url = new URL("http://localhost:" + String.valueOf(port) +
                    "/anything");
-     con = (HttpURLConnection)url.openConnection();
+     con = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
 
      con.setIfModifiedSince(date.getTime());
      con.connect();
--- a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary REGISTRY RegistryRunner
+ * @build TestLibrary RegistryVM RegistryRunner
  * @run main/othervm DeadCachedConnection
  */
 
@@ -100,7 +100,7 @@
 
     public static int makeRegistry(int port) {
         try {
-            subreg = REGISTRY.createREGISTRY(System.out, System.err, "", port);
+            subreg = RegistryVM.createRegistryVM(System.out, System.err, "", port);
             subreg.start();
             int regPort = subreg.getPort();
             System.out.println("Starting registry on port " + regPort);
@@ -113,11 +113,11 @@
         return -1;
     }
 
-    private static REGISTRY subreg = null;
+    private static RegistryVM subreg = null;
 
     public static void killRegistry() throws InterruptedException {
         if (subreg != null) {
-            subreg.shutdown();
+            subreg.cleanup();
             subreg = null;
         }
     }
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
 
 import java.security.*;
 import java.security.cert.*;
-import java.security.cert.Certificate;
 
 import javax.net.ssl.*;
 
@@ -61,6 +60,8 @@
 
     private static PeerFactory peerFactory;
 
+    static final CountDownLatch clientCondition = new CountDownLatch(1);
+
     static abstract class Server implements Runnable {
 
         final CipherTest cipherTest;
@@ -313,6 +314,10 @@
             }
             threads[i].start();
         }
+
+        // The client threads are ready.
+        clientCondition.countDown();
+
         try {
             for (int i = 0; i < THREADS; i++) {
                 threads[i].join();
@@ -367,6 +372,10 @@
                 try {
                     runTest(params);
                     System.out.println("Passed " + params);
+                } catch (SocketTimeoutException ste) {
+                    System.out.println("The client connects to the server timeout, "
+                            + "so ignore the test.");
+                    break;
                 } catch (Exception e) {
                     cipherTest.setFailed();
                     System.out.println("** Failed " + params + "**");
--- a/jdk/test/sun/security/pkcs11/sslecc/JSSEClient.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/security/pkcs11/sslecc/JSSEClient.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
  * 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,10 +23,7 @@
 
 import java.io.*;
 import java.net.*;
-import java.util.*;
 
-import java.security.*;
-import java.security.cert.*;
 import java.security.cert.Certificate;
 
 import javax.net.ssl.*;
@@ -46,10 +43,30 @@
         SSLSocket socket = null;
         try {
             keyManager.setAuthType(params.clientAuth);
-            sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {cipherTest.trustManager}, cipherTest.secureRandom);
-            SSLSocketFactory factory = (SSLSocketFactory)sslContext.getSocketFactory();
-            socket = (SSLSocket)factory.createSocket("127.0.0.1", cipherTest.serverPort);
-            socket.setSoTimeout(cipherTest.TIMEOUT);
+            sslContext.init(
+                    new KeyManager[] { keyManager },
+                    new TrustManager[] { CipherTest.trustManager },
+                    CipherTest.secureRandom);
+            SSLSocketFactory factory
+                    = (SSLSocketFactory) sslContext.getSocketFactory();
+
+            socket = (SSLSocket) factory.createSocket();
+            try {
+                socket.connect(new InetSocketAddress("127.0.0.1",
+                        CipherTest.serverPort), 15000);
+            } catch (IOException ioe) {
+                // The server side may be impacted by naughty test cases or
+                // third party routines, and cannot accept connections.
+                //
+                // Just ignore the test if the connection cannot be
+                // established.
+                System.out.println(
+                        "Cannot make a connection in 15 seconds. " +
+                        "Ignore in client side.");
+                return;
+            }
+
+            socket.setSoTimeout(CipherTest.TIMEOUT);
             socket.setEnabledCipherSuites(new String[] {params.cipherSuite});
             socket.setEnabledProtocols(new String[] {params.protocol});
             InputStream in = socket.getInputStream();
--- a/jdk/test/sun/security/pkcs11/sslecc/JSSEServer.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/security/pkcs11/sslecc/JSSEServer.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.SocketTimeoutException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLServerSocket;
@@ -40,24 +43,37 @@
     JSSEServer(CipherTest cipherTest) throws Exception {
         super(cipherTest);
         SSLContext serverContext = SSLContext.getInstance("TLS");
-        serverContext.init(new KeyManager[] {cipherTest.keyManager}, new TrustManager[] {cipherTest.trustManager}, cipherTest.secureRandom);
+        serverContext.init(
+                new KeyManager[] { CipherTest.keyManager },
+                new TrustManager[] { CipherTest.trustManager },
+                CipherTest.secureRandom);
 
         SSLServerSocketFactory factory = (SSLServerSocketFactory)serverContext.getServerSocketFactory();
         serverSocket = (SSLServerSocket)factory.createServerSocket(0);
-        cipherTest.serverPort = serverSocket.getLocalPort();
+        serverSocket.setSoTimeout(CipherTest.TIMEOUT);
+        CipherTest.serverPort = serverSocket.getLocalPort();
         serverSocket.setEnabledCipherSuites(factory.getSupportedCipherSuites());
         serverSocket.setWantClientAuth(true);
     }
 
     @Override
     public void run() {
-        System.out.println("JSSE Server listening on port " + cipherTest.serverPort);
+        System.out.println("JSSE Server listening on port " + CipherTest.serverPort);
         Executor exec = Executors.newFixedThreadPool
                             (CipherTest.THREADS, DaemonThreadFactory.INSTANCE);
+
         try {
+            if (!CipherTest.clientCondition.await(CipherTest.TIMEOUT,
+                    TimeUnit.MILLISECONDS)) {
+                System.out.println(
+                        "The client is not the expected one or timeout. "
+                                + "Ignore in server side.");
+                return;
+            }
+
             while (true) {
                 final SSLSocket socket = (SSLSocket)serverSocket.accept();
-                socket.setSoTimeout(cipherTest.TIMEOUT);
+                socket.setSoTimeout(CipherTest.TIMEOUT);
                 Runnable r = new Runnable() {
                     @Override
                     public void run() {
@@ -86,11 +102,12 @@
                 };
                 exec.execute(r);
             }
-        } catch (IOException e) {
+        } catch (SocketTimeoutException ste) {
+            System.out.println("The server got timeout for waiting for the connection, "
+                    + "so ignore the test.");
+        } catch (Exception e) {
             cipherTest.setFailed();
             e.printStackTrace();
-            //
         }
     }
-
 }
--- a/jdk/test/sun/security/tools/keytool/PrintSSL.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/security/tools/keytool/PrintSSL.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,7 @@
  * @test
  * @bug 6480981 8160624
  * @summary keytool should be able to import certificates from remote SSL server
- * @library /lib/security
- * @library /lib/testlibrary
+ * @library /test/lib
  * @run main/othervm PrintSSL
  */
 
@@ -36,7 +35,8 @@
 import java.util.concurrent.CountDownLatch;
 import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSocket;
-import jdk.testlibrary.OutputAnalyzer;
+import jdk.test.lib.SecurityTools;
+import jdk.test.lib.process.OutputAnalyzer;
 
 public class PrintSSL {
 
--- a/jdk/test/sun/security/tools/keytool/ReadJar.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/sun/security/tools/keytool/ReadJar.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * 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,14 +25,15 @@
  * @test
  * @bug 6890872 8168882
  * @summary keytool -printcert to recognize signed jar files
- * @library /lib/security
+ * @library /test/lib
  * @library /lib/testlibrary
  */
 
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import jdk.test.lib.SecurityTools;
+import jdk.test.lib.process.OutputAnalyzer;
 import jdk.testlibrary.JarUtils;
-import jdk.testlibrary.OutputAnalyzer;
 
 public class ReadJar {
 
--- a/jdk/test/tools/jar/InputFilesTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/tools/jar/InputFilesTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -102,6 +102,7 @@
                 "META-INF/MANIFEST.MF" + nl +
                 "testfile1" + nl +
                 "testfile2" + nl +
+                "META-INF/versions/9/" + nl +
                 "META-INF/versions/9/testfile3" + nl +
                 "META-INF/versions/9/testfile4" + nl;
         rm("test.jar test1 test2 test3 test4");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/Basic.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8146486 8172432
+ * @summary Fail to create a MR modular JAR with a versioned entry in
+ *          base-versioned empty package
+ * @modules java.base/jdk.internal.module
+ *          jdk.compiler
+ *          jdk.jartool
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run testng Basic
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Version;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.Set;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipFile;
+
+import jdk.internal.module.ModuleInfoExtender;
+import jdk.testlibrary.FileUtils;
+
+public class Basic {
+    private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+           .orElseThrow(() -> new RuntimeException("jar tool not found"));
+    private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+            .orElseThrow(() -> new RuntimeException("javac tool not found"));
+    private final String linesep = System.lineSeparator();
+    private final Path testsrc;
+    private final Path userdir;
+    private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
+    private final PrintStream out = new PrintStream(outbytes, true);
+    private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
+    private final PrintStream err = new PrintStream(errbytes, true);
+
+    public Basic() throws IOException {
+        testsrc = Paths.get(System.getProperty("test.src"));
+        userdir = Paths.get(System.getProperty("user.dir", "."));
+
+        // compile the classes directory
+        Path source = testsrc.resolve("src").resolve("classes");
+        Path destination = Paths.get("classes");
+        javac(source, destination);
+
+        // compile the mr9 directory including module-info.java
+        source = testsrc.resolve("src").resolve("mr9");
+        destination = Paths.get("mr9");
+        javac(source, destination);
+
+        // move module-info.class for later use
+        Files.move(destination.resolve("module-info.class"),
+                Paths.get("module-info.class"));
+    }
+
+    private void javac(Path source, Path destination) throws IOException {
+        String[] args = Stream.concat(
+                Stream.of("-d", destination.toString()),
+                Files.walk(source)
+                        .map(Path::toString)
+                        .filter(s -> s.endsWith(".java"))
+        ).toArray(String[]::new);
+        JAVAC_TOOL.run(System.out, System.err, args);
+    }
+
+    private int jar(String cmd) {
+        outbytes.reset();
+        errbytes.reset();
+        return JAR_TOOL.run(out, err, cmd.split(" +"));
+    }
+
+    @AfterClass
+    public void cleanup() throws IOException {
+        Files.walk(userdir, 1)
+                .filter(p -> !p.equals(userdir))
+                .forEach(p -> {
+                    try {
+                        if (Files.isDirectory(p)) {
+                            FileUtils.deleteFileTreeWithRetry(p);
+                        } else {
+                            FileUtils.deleteFileIfExistsWithRetry(p);
+                        }
+                    } catch (IOException x) {
+                        throw new UncheckedIOException(x);
+                    }
+                });
+    }
+
+    // updates a valid multi-release jar with a new public class in
+    // versioned section and fails
+    @Test
+    public void test1() {
+        // successful build of multi-release jar
+        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+        Assert.assertEquals(rc, 0);
+
+        jar("-tf mmr.jar");
+
+        Set<String> actual = lines(outbytes);
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/p/Hi.class"
+        );
+        Assert.assertEquals(actual, expected);
+
+        // failed build because of new public class
+        rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
+        Assert.assertEquals(rc, 1);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
+    }
+
+    // updates a valid multi-release jar with a module-info class and new
+    // concealed public class in versioned section and succeeds
+    @Test
+    public void test2() {
+        // successful build of multi-release jar
+        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+        Assert.assertEquals(rc, 0);
+
+        // successful build because of module-info and new public class
+        rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
+        Assert.assertEquals(rc, 0);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
+
+        jar("-tf mmr.jar");
+
+        Set<String> actual = lines(outbytes);
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/p/Hi.class",
+                "META-INF/versions/9/p/internal/Bar.class",
+                "module-info.class"
+        );
+        Assert.assertEquals(actual, expected);
+    }
+
+    // jar tool fails building mmr.jar because of new public class
+    @Test
+    public void test3() {
+        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
+        Assert.assertEquals(rc, 1);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
+    }
+
+    // jar tool succeeds building mmr.jar because of concealed package
+    @Test
+    public void test4() {
+        int rc = jar("-cf mmr.jar module-info.class -C classes . " +
+                "--release 9 module-info.class -C mr9 .");
+        Assert.assertEquals(rc, 0);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
+
+        jar("-tf mmr.jar");
+
+        Set<String> actual = lines(outbytes);
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "module-info.class",
+                "META-INF/versions/9/module-info.class",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/",
+                "META-INF/versions/9/p/",
+                "META-INF/versions/9/p/Hi.class",
+                "META-INF/versions/9/p/internal/",
+                "META-INF/versions/9/p/internal/Bar.class"
+        );
+        Assert.assertEquals(actual, expected);
+    }
+
+    // jar tool does two updates, no exported packages, all concealed
+    @Test
+    public void test5() throws IOException {
+        // compile the mr10 directory
+        Path source = testsrc.resolve("src").resolve("mr10");
+        Path destination = Paths.get("mr10");
+        javac(source, destination);
+
+        // create a directory for this tests special files
+        Files.createDirectory(Paths.get("test5"));
+
+        // create an empty module-info.java
+        String hi = "module hi {" + linesep + "}" + linesep;
+        Path modinfo = Paths.get("test5", "module-info.java");
+        Files.write(modinfo, hi.getBytes());
+
+        // and compile it
+        javac(modinfo, Paths.get("test5"));
+
+        int rc = jar("--create --file mr.jar -C classes .");
+        Assert.assertEquals(rc, 0);
+
+        rc = jar("--update --file mr.jar -C test5 module-info.class"
+                + " --release 9 -C mr9 .");
+        Assert.assertEquals(rc, 0);
+
+        jar("tf mr.jar");
+
+        Set<String> actual = lines(outbytes);
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/",
+                "META-INF/versions/9/p/",
+                "META-INF/versions/9/p/Hi.class",
+                "META-INF/versions/9/p/internal/",
+                "META-INF/versions/9/p/internal/Bar.class",
+                "module-info.class"
+        );
+        Assert.assertEquals(actual, expected);
+
+        jar("-d --file mr.jar");
+
+        actual = lines(outbytes);
+        expected = Set.of(
+                "hi",
+                "requires mandated java.base",
+                "contains p",
+                "contains p.internal"
+        );
+        Assert.assertEquals(actual, expected);
+
+        rc = jar("--update --file mr.jar --release 10 -C mr10 .");
+        Assert.assertEquals(rc, 0);
+
+        jar("tf mr.jar");
+
+        actual = lines(outbytes);
+        expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/",
+                "META-INF/versions/9/p/",
+                "META-INF/versions/9/p/Hi.class",
+                "META-INF/versions/9/p/internal/",
+                "META-INF/versions/9/p/internal/Bar.class",
+                "META-INF/versions/10/",
+                "META-INF/versions/10/p/",
+                "META-INF/versions/10/p/internal/",
+                "META-INF/versions/10/p/internal/bar/",
+                "META-INF/versions/10/p/internal/bar/Gee.class",
+                "module-info.class"
+        );
+        Assert.assertEquals(actual, expected);
+
+        jar("-d --file mr.jar");
+
+        actual = lines(outbytes);
+        expected = Set.of(
+                "hi",
+                "requires mandated java.base",
+                "contains p",
+                "contains p.internal",
+                "contains p.internal.bar"
+        );
+        Assert.assertEquals(actual, expected);
+    }
+
+    // root and versioned module-info entries have different main-class, version
+    // attributes
+    @Test
+    public void test6() throws IOException {
+        // create a directory for this tests special files
+        Files.createDirectory(Paths.get("test6"));
+        Files.createDirectory(Paths.get("test6-v9"));
+
+        // compile the classes directory
+        Path src = testsrc.resolve("src").resolve("classes");
+        Path dst = Paths.get("test6");
+        javac(src, dst);
+
+        byte[] mdBytes = Files.readAllBytes(Paths.get("module-info.class"));
+
+        ModuleInfoExtender mie = ModuleInfoExtender.newExtender(
+            new ByteArrayInputStream(mdBytes));
+
+        mie.mainClass("foo.main");
+        mie.version(Version.parse("1.0"));
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        mie.write(baos);
+        Files.write(Paths.get("test6", "module-info.class"), baos.toByteArray());
+        Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
+
+        int rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
+        Assert.assertEquals(rc, 0);
+
+
+        // different main-class
+        mie = ModuleInfoExtender.newExtender(new ByteArrayInputStream(mdBytes));
+        mie.mainClass("foo.main2");
+        mie.version(Version.parse("1.0"));
+        baos.reset();
+        mie.write(baos);
+        Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
+
+        rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
+        Assert.assertEquals(rc, 1);
+
+        Assert.assertTrue(Message.CONTAINS_DIFFERENT_MAINCLASS.match(
+            new String(errbytes.toByteArray()),
+            "META-INF/versions/9/module-info.class"));
+
+        // different version
+        mie = ModuleInfoExtender.newExtender(new ByteArrayInputStream(mdBytes));
+        mie.mainClass("foo.main");
+        mie.version(Version.parse("2.0"));
+        baos.reset();
+        mie.write(baos);
+        Files.write(Paths.get("test6-v9", "module-info.class"), baos.toByteArray());
+
+        rc = jar("--create --file mmr.jar -C test6 . --release 9 -C test6-v9 .");
+        Assert.assertEquals(rc, 1);
+
+        Assert.assertTrue(Message.CONTAINS_DIFFERENT_VERSION.match(
+            new String(errbytes.toByteArray()),
+            "META-INF/versions/9/module-info.class"));
+
+    }
+
+    // versioned mmr without root module-info.class
+    @Test
+    public void test7() throws IOException {
+        // create a directory for this tests special files
+        Files.createDirectory(Paths.get("test7"));
+        Files.createDirectory(Paths.get("test7-v9"));
+        Files.createDirectory(Paths.get("test7-v10"));
+
+        // compile the classes directory
+        Path src = testsrc.resolve("src").resolve("classes");
+        Path dst = Paths.get("test7");
+        javac(src, dst);
+
+        // move module-info.class to v9 later use
+        Files.copy(Paths.get("module-info.class"),
+                   Paths.get("test7-v9", "module-info.class"));
+
+        Files.copy(Paths.get("test7-v9", "module-info.class"),
+                   Paths.get("test7-v10", "module-info.class"));
+
+        int rc = jar("--create --file mmr.jar --main-class=foo.main -C test7 . --release 9 -C test7-v9 . --release 10 -C test7-v10 .");
+
+System.out.println("-----------------------");
+System.out.println( new String(errbytes.toByteArray()));
+
+
+        Assert.assertEquals(rc, 0);
+
+
+        jar("-tf mmr.jar");
+
+System.out.println("-----------------------");
+System.out.println( new String(outbytes.toByteArray()));
+
+        Optional<String> exp = Optional.of("foo.main");
+        try (ZipFile zf = new ZipFile("mmr.jar")) {
+            Assert.assertTrue(zf.getEntry("module-info.class") == null);
+
+            ModuleDescriptor md = ModuleDescriptor.read(
+                zf.getInputStream(zf.getEntry("META-INF/versions/9/module-info.class")));
+            Assert.assertEquals(md.mainClass(), exp);
+
+            md = ModuleDescriptor.read(
+                zf.getInputStream(zf.getEntry("META-INF/versions/10/module-info.class")));
+            Assert.assertEquals(md.mainClass(), exp);
+        }
+    }
+
+    private static Set<String> lines(ByteArrayOutputStream baos) {
+        String s = new String(baos.toByteArray());
+        return Arrays.stream(s.split("\\R"))
+                     .map(l -> l.trim())
+                     .filter(l -> l.length() > 0)
+                     .collect(Collectors.toSet());
+    }
+
+    static enum Message {
+        CONTAINS_DIFFERENT_MAINCLASS(
+          ": module-info.class in a versioned directory contains different \"main-class\""
+        ),
+        CONTAINS_DIFFERENT_VERSION(
+          ": module-info.class in a versioned directory contains different \"version\""
+        ),
+        NOT_FOUND_IN_BASE_ENTRY(
+          ", contains a new public class not found in base entries"
+        ),
+        NEW_CONCEALED_PACKAGE_WARNING(
+            " is a public class" +
+            " in a concealed package, placing this jar on the class path will result" +
+            " in incompatible public interfaces"
+        );
+
+        final String msg;
+        Message(String msg) {
+            this.msg = msg;
+        }
+
+        /*
+         * Test if the given output contains this message ignoring the line break.
+         */
+        boolean match(String output, String entry) {
+            System.out.println("Expected: " + entry + msg);
+            System.out.println("Found: " + output);
+            return Arrays.stream(output.split("\\R"))
+                         .collect(Collectors.joining(" "))
+                         .contains(entry + msg);
+        }
+    }
+}
--- a/jdk/test/tools/jar/mmrjar/ConcealedPackage.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8146486
- * @summary Fail to create a MR modular JAR with a versioned entry in
- *          base-versioned empty package
- * @modules jdk.compiler
- *          jdk.jartool
- * @library /lib/testlibrary
- * @build jdk.testlibrary.FileUtils
- * @run testng ConcealedPackage
- */
-
-import org.testng.Assert;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.Set;
-import java.util.spi.ToolProvider;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import jdk.testlibrary.FileUtils;
-
-public class ConcealedPackage {
-    private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
-           .orElseThrow(() -> new RuntimeException("jar tool not found"));
-    private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
-            .orElseThrow(() -> new RuntimeException("javac tool not found"));
-    private final String linesep = System.lineSeparator();
-    private final Path testsrc;
-    private final Path userdir;
-    private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
-    private final PrintStream out = new PrintStream(outbytes, true);
-    private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
-    private final PrintStream err = new PrintStream(errbytes, true);
-
-    public ConcealedPackage() throws IOException {
-        testsrc = Paths.get(System.getProperty("test.src"));
-        userdir = Paths.get(System.getProperty("user.dir", "."));
-
-        // compile the classes directory
-        Path source = testsrc.resolve("src").resolve("classes");
-        Path destination = Paths.get("classes");
-        javac(source, destination);
-
-        // compile the mr9 directory including module-info.java
-        source = testsrc.resolve("src").resolve("mr9");
-        destination = Paths.get("mr9");
-        javac(source, destination);
-
-        // move module-info.class for later use
-        Files.move(destination.resolve("module-info.class"),
-                Paths.get("module-info.class"));
-    }
-
-    private void javac(Path source, Path destination) throws IOException {
-        String[] args = Stream.concat(
-                Stream.of("-d", destination.toString()),
-                Files.walk(source)
-                        .map(Path::toString)
-                        .filter(s -> s.endsWith(".java"))
-        ).toArray(String[]::new);
-        JAVAC_TOOL.run(System.out, System.err, args);
-    }
-
-    private int jar(String cmd) {
-        outbytes.reset();
-        errbytes.reset();
-        return JAR_TOOL.run(out, err, cmd.split(" +"));
-    }
-
-    @AfterClass
-    public void cleanup() throws IOException {
-        Files.walk(userdir, 1)
-                .filter(p -> !p.equals(userdir))
-                .forEach(p -> {
-                    try {
-                        if (Files.isDirectory(p)) {
-                            FileUtils.deleteFileTreeWithRetry(p);
-                        } else {
-                            FileUtils.deleteFileIfExistsWithRetry(p);
-                        }
-                    } catch (IOException x) {
-                        throw new UncheckedIOException(x);
-                    }
-                });
-    }
-
-    // updates a valid multi-release jar with a new public class in
-    // versioned section and fails
-    @Test
-    public void test1() {
-        // successful build of multi-release jar
-        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
-        Assert.assertEquals(rc, 0);
-
-        jar("-tf mmr.jar");
-
-        Set<String> actual = lines(outbytes);
-        Set<String> expected = Set.of(
-                "META-INF/",
-                "META-INF/MANIFEST.MF",
-                "p/",
-                "p/Hi.class",
-                "META-INF/versions/9/p/Hi.class"
-        );
-        Assert.assertEquals(actual, expected);
-
-        // failed build because of new public class
-        rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
-        Assert.assertEquals(rc, 1);
-
-        String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
-    }
-
-    // updates a valid multi-release jar with a module-info class and new
-    // concealed public class in versioned section and succeeds
-    @Test
-    public void test2() {
-        // successful build of multi-release jar
-        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
-        Assert.assertEquals(rc, 0);
-
-        // successful build because of module-info and new public class
-        rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
-        Assert.assertEquals(rc, 0);
-
-        String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
-
-        jar("-tf mmr.jar");
-
-        Set<String> actual = lines(outbytes);
-        Set<String> expected = Set.of(
-                "META-INF/",
-                "META-INF/MANIFEST.MF",
-                "p/",
-                "p/Hi.class",
-                "META-INF/versions/9/p/Hi.class",
-                "META-INF/versions/9/p/internal/Bar.class",
-                "module-info.class"
-        );
-        Assert.assertEquals(actual, expected);
-    }
-
-    // jar tool fails building mmr.jar because of new public class
-    @Test
-    public void test3() {
-        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
-        Assert.assertEquals(rc, 1);
-
-        String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
-    }
-
-    // jar tool succeeds building mmr.jar because of concealed package
-    @Test
-    public void test4() {
-        int rc = jar("-cf mmr.jar module-info.class -C classes . " +
-                "--release 9 module-info.class -C mr9 .");
-        Assert.assertEquals(rc, 0);
-
-        String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
-
-        jar("-tf mmr.jar");
-
-        Set<String> actual = lines(outbytes);
-        Set<String> expected = Set.of(
-                "META-INF/",
-                "META-INF/MANIFEST.MF",
-                "module-info.class",
-                "META-INF/versions/9/module-info.class",
-                "p/",
-                "p/Hi.class",
-                "META-INF/versions/9/p/",
-                "META-INF/versions/9/p/Hi.class",
-                "META-INF/versions/9/p/internal/",
-                "META-INF/versions/9/p/internal/Bar.class"
-        );
-        Assert.assertEquals(actual, expected);
-    }
-
-    // jar tool does two updates, no exported packages, all concealed
-    @Test
-    public void test5() throws IOException {
-        // compile the mr10 directory
-        Path source = testsrc.resolve("src").resolve("mr10");
-        Path destination = Paths.get("mr10");
-        javac(source, destination);
-
-        // create a directory for this tests special files
-        Files.createDirectory(Paths.get("test5"));
-
-        // create an empty module-info.java
-        String hi = "module hi {" + linesep + "}" + linesep;
-        Path modinfo = Paths.get("test5", "module-info.java");
-        Files.write(modinfo, hi.getBytes());
-
-        // and compile it
-        javac(modinfo, Paths.get("test5"));
-
-        int rc = jar("--create --file mr.jar -C classes .");
-        Assert.assertEquals(rc, 0);
-
-        rc = jar("--update --file mr.jar -C test5 module-info.class"
-                + " --release 9 -C mr9 .");
-        Assert.assertEquals(rc, 0);
-
-        jar("tf mr.jar");
-
-        Set<String> actual = lines(outbytes);
-        Set<String> expected = Set.of(
-                "META-INF/",
-                "META-INF/MANIFEST.MF",
-                "p/",
-                "p/Hi.class",
-                "META-INF/versions/9/p/",
-                "META-INF/versions/9/p/Hi.class",
-                "META-INF/versions/9/p/internal/",
-                "META-INF/versions/9/p/internal/Bar.class",
-                "module-info.class"
-        );
-        Assert.assertEquals(actual, expected);
-
-        jar("-d --file mr.jar");
-
-        actual = lines(outbytes);
-        expected = Set.of(
-                "hi",
-                "requires mandated java.base",
-                "contains p",
-                "contains p.internal"
-        );
-        Assert.assertEquals(actual, expected);
-
-        rc = jar("--update --file mr.jar --release 10 -C mr10 .");
-        Assert.assertEquals(rc, 0);
-
-        jar("tf mr.jar");
-
-        actual = lines(outbytes);
-        expected = Set.of(
-                "META-INF/",
-                "META-INF/MANIFEST.MF",
-                "p/",
-                "p/Hi.class",
-                "META-INF/versions/9/p/",
-                "META-INF/versions/9/p/Hi.class",
-                "META-INF/versions/9/p/internal/",
-                "META-INF/versions/9/p/internal/Bar.class",
-                "META-INF/versions/10/p/",
-                "META-INF/versions/10/p/internal/",
-                "META-INF/versions/10/p/internal/bar/",
-                "META-INF/versions/10/p/internal/bar/Gee.class",
-                "module-info.class"
-        );
-        Assert.assertEquals(actual, expected);
-
-        jar("-d --file mr.jar");
-
-        actual = lines(outbytes);
-        expected = Set.of(
-                "hi",
-                "requires mandated java.base",
-                "contains p",
-                "contains p.internal",
-                "contains p.internal.bar"
-        );
-        Assert.assertEquals(actual, expected);
-    }
-
-    private static Set<String> lines(ByteArrayOutputStream baos) {
-        String s = new String(baos.toByteArray());
-        return Arrays.stream(s.split("\\R"))
-                     .map(l -> l.trim())
-                     .filter(l -> l.length() > 0)
-                     .collect(Collectors.toSet());
-    }
-
-    static enum Message {
-        NOT_FOUND_IN_BASE_ENTRY(
-          ", contains a new public class not found in base entries"
-        ),
-        NEW_CONCEALED_PACKAGE_WARNING(
-            " is a public class" +
-            " in a concealed package, placing this jar on the class path will result" +
-            " in incompatible public interfaces"
-        );
-
-        final String msg;
-        Message(String msg) {
-            this.msg = msg;
-        }
-
-        /*
-         * Test if the given output contains this message ignoring the line break.
-         */
-        boolean match(String output, String entry) {
-            System.out.println("Expected: " + entry + msg);
-            System.out.println("Found: " + output);
-            return Arrays.stream(output.split("\\R"))
-                         .collect(Collectors.joining(" "))
-                         .contains(entry + msg);
-        }
-    }
-}
--- a/jdk/test/tools/jar/modularJar/Basic.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/tools/jar/modularJar/Basic.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
 
 /*
  * @test
- * @bug 8167328
+ * @bug 8167328 8171830
  * @library /lib/testlibrary
  * @modules jdk.compiler
  *          jdk.jartool
@@ -241,6 +241,11 @@
 
         java(mp, FOO.moduleName + "/" + FOO.mainClass)
             .assertSuccess()
+.resultChecker(r -> {
+        System.out.println("===================================");
+        System.out.println(r.output);
+        System.out.println("===================================");
+})
             .resultChecker(r -> assertModuleData(r, FOO));
         try (InputStream fis = Files.newInputStream(modularJar);
              JarInputStream jis = new JarInputStream(fis)) {
@@ -417,6 +422,7 @@
         jar("--update",
             "--file=" + modularJar.toString(),
             "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
             "-m", mrjarDir.resolve("META-INF/MANIFEST.MF").toRealPath().toString(),
             "-C", mrjarDir.toString(), "META-INF/versions/9/module-info.class")
             .assertSuccess();
@@ -734,6 +740,25 @@
     }
 
     @Test
+    public void exportCreateWithMissingPkg() throws IOException {
+
+        Path foobar = TEST_SRC.resolve("src").resolve("foobar");
+        Path dst = Files.createDirectories(MODULE_CLASSES.resolve("foobar"));
+        javac(dst, null, sourceList(foobar));
+
+        Path mp = Paths.get("exportWithMissingPkg");
+        createTestDir(mp);
+        Path modClasses = dst;
+        Path modularJar = mp.resolve("foofoo.jar");
+
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "module-info.class",
+            "-C", modClasses.toString(), "jdk/test/foo/Foo.class")
+            .assertFailure();
+    }
+
+    @Test
     public void printModuleDescriptorFoo() throws IOException {
         Path mp = Paths.get("printModuleDescriptorFoo");
         createTestDir(mp);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/modularJar/src/foobar/Bar.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.bar;
+
+public class Bar {
+    public static void main(String[] args) {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/modularJar/src/foobar/Foo.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.foo;
+
+public class Foo {
+    public static void main(String[] args) {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/modularJar/src/foobar/module-info.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.
+ */
+
+module foo {
+    exports jdk.test.foo;
+    exports jdk.test.bar;
+    opens jdk.test.foo;
+    opens jdk.test.bar;
+}
--- a/jdk/test/tools/jar/multiRelease/Basic1.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/tools/jar/multiRelease/Basic1.java	Wed Jul 05 22:42:01 2017 +0200
@@ -62,15 +62,20 @@
         Path source = Paths.get(src, "data", test, "base", "version");
         javac(classes, source.resolve("Main.java"), source.resolve("Version.java"));
 
-        Path v9 = Paths.get("v9").resolve("META-INF").resolve("versions").resolve("9");
+        Path v9 = Paths.get("v9");
         Files.createDirectories(v9);
         source = Paths.get(src, "data", test, "v9", "version");
         javac(v9, source.resolve("Version.java"));
 
-        Path v10 = Paths.get("v10").resolve("META-INF").resolve("versions").resolve("10");
+        Path v10 = Paths.get("v10");
         Files.createDirectories(v10);
         source = Paths.get(src, "data", test, "v10", "version");
         javac(v10, source.resolve("Version.java"));
+
+        Path v10_1 = Paths.get("v10_1").resolve("META-INF").resolve("versions").resolve("v10");
+        Files.createDirectories(v10_1);
+        source = Paths.get(src, "data", test, "v10", "version");
+        javac(v10_1, source.resolve("Version.java"));
     }
 
     @Test
@@ -95,28 +100,30 @@
             new String[] {"classes", "base", "version", "Version.class"},
 
             "META-INF/versions/9/version/Version.class",
-            new String[] {"v9", "META-INF", "versions", "9", "version", "Version.class"},
+            new String[] {"v9", "version", "Version.class"},
 
             "META-INF/versions/10/version/Version.class",
-            new String[] {"v10", "META-INF", "versions", "10", "version", "Version.class"}
+            new String[] {"v10", "version", "Version.class"}
         );
 
         compare(jarfile, names);
     }
 
+
     @Test
     public void testFail() throws IOException {
         String jarfile = "test.jar";
         Path classes = Paths.get("classes");
-        Path v9 = Paths.get("v9");
-        Path v10 = Paths.get("v10");
+        Path v10 = Paths.get("v10_1");
 
         jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
-            "--release", "9", "-C", v10.toString(), ".")
+            "--release", "10", "-C", v10.toString(), ".")
             .assertFailure()
             .outputContains("unexpected versioned entry META-INF/versions/");
     }
 
+
+
     private void checkMultiRelease(String jarFile, boolean expected) throws IOException {
         try (JarFile jf = new JarFile(new File(jarFile), true, ZipFile.OPEN_READ,
                 JarFile.runtimeVersion())) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/RuntimeTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test Multi-Release jar usage in runtime
+ * @library /test/lib
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.JDKToolLauncher
+ *        jdk.test.lib.process.OutputAnalyzer
+ *        jdk.test.lib.process.ProcessTools
+ *        CompilerUtils RuntimeTest
+ * @run testng RuntimeTest
+ */
+
+import static org.testng.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class RuntimeTest {
+    public static final int SUCCESS = 0;
+    private final String src = System.getProperty("test.src", ".");
+    private final String usr = System.getProperty("user.dir", ".");
+
+    @DataProvider(name = "jarFiles")
+    Object[][] jarFiles() {
+        return new Object[][] { { "MV_BOTH.jar", 9, 9, 9 },
+                { "MV_ONLY_9.jar", 9, 9, 9 },
+                { "NON_MV.jar", 8, 8, 8 } };
+    }
+
+    @BeforeClass
+    protected void setUpTest() throws Throwable {
+        compile();
+        Path classes = Paths.get("classes");
+        jar("cfm", "MV_BOTH.jar", "manifest.txt",
+                "-C", classes.resolve("base").toString(), ".",
+                "--release", "9", "-C", classes.resolve("v9").toString(), ".",
+                "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+                .shouldHaveExitValue(0);
+
+        jar("cfm", "MV_ONLY_9.jar", "manifest.txt",
+                "-C", classes.resolve("base").toString(), ".",
+                "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+                .shouldHaveExitValue(0);
+        jar("cfm", "NON_MV.jar", "manifest.txt",
+                "-C", classes.resolve("base").toString(), ".")
+                .shouldHaveExitValue(0);
+    }
+
+    @Test(dataProvider = "jarFiles")
+    public void testClasspath(String jar, int mainVer, int helperVer,
+            int resVer) throws Throwable {
+        String[] command = { "-cp", jar, "testpackage.Main" };
+        System.out.println("Command arguments:" + Arrays.asList(command));
+        System.out.println();
+        java(command).shouldHaveExitValue(SUCCESS)
+                .shouldContain("Main version: " + mainVer)
+                .shouldContain("Helpers version: " + helperVer)
+                .shouldContain("Resource version: " + resVer);
+    }
+
+    @Test(dataProvider = "jarFiles")
+    void testMVJarAsLib(String jar, int mainVer, int helperVer, int resVer)
+            throws Throwable {
+        String[] apps = { "UseByImport", "UseByReflection" };
+        for (String app : apps) {
+            String[] command = {"-cp",
+                    jar + File.pathSeparatorChar + "classes/test/", app };
+            System.out.println("Command arguments:" + Arrays.asList(command));
+            System.out.println();
+            java(command).shouldHaveExitValue(SUCCESS)
+                    .shouldContain("Main version: " + mainVer)
+                    .shouldContain("Helpers version: " + helperVer)
+                    .shouldContain("Resource version: " + resVer);
+        }
+    }
+
+    @Test(dataProvider = "jarFiles")
+    void testJavaJar(String jar, int mainVer, int helperVer, int resVer)
+            throws Throwable {
+        String[] command = { "-jar", jar };
+        System.out.println("Command arguments:" + Arrays.asList(command));
+        System.out.println();
+        java(command).shouldHaveExitValue(SUCCESS)
+                .shouldContain("Main version: " + mainVer)
+                .shouldContain("Helpers version: " + helperVer)
+                .shouldContain("Resource version: " + resVer);
+    }
+
+    @Test(dataProvider = "jarFiles")
+    void testURLClassLoader(String jarName, int mainVer, int helperVer,
+            int resVer) throws ClassNotFoundException, NoSuchMethodException,
+            IllegalAccessException, IllegalArgumentException,
+            InvocationTargetException, IOException {
+        Path pathToJAR = Paths.get(jarName).toAbsolutePath();
+        URL jarURL1 = new URL("jar:file:" + pathToJAR + "!/");
+        URL jarURL2 = new URL("file:///" + pathToJAR);
+        testURLClassLoaderURL(jarURL1, mainVer, helperVer, resVer);
+        testURLClassLoaderURL(jarURL2, mainVer, helperVer, resVer);
+    }
+
+    private static void testURLClassLoaderURL(URL jarURL,
+            int mainVersionExpected, int helperVersionExpected,
+            int resourceVersionExpected) throws ClassNotFoundException,
+            NoSuchMethodException, IllegalAccessException,
+            IllegalArgumentException, InvocationTargetException, IOException {
+        System.out.println(
+                "Testing URLClassLoader MV JAR support for URL: " + jarURL);
+        URL[] urls = { jarURL };
+        int mainVersionActual;
+        int helperVersionActual;
+        int resourceVersionActual;
+        try (URLClassLoader cl = URLClassLoader.newInstance(urls)) {
+            Class c = cl.loadClass("testpackage.Main");
+            Method getMainVersion = c.getMethod("getMainVersion");
+            mainVersionActual = (int) getMainVersion.invoke(null);
+            Method getHelperVersion = c.getMethod("getHelperVersion");
+            helperVersionActual = (int) getHelperVersion.invoke(null);
+            try (InputStream ris = cl.getResourceAsStream("versionResource");
+                    BufferedReader br = new BufferedReader(
+                            new InputStreamReader(ris))) {
+                resourceVersionActual = Integer.parseInt(br.readLine());
+            }
+        }
+
+        assertEquals(mainVersionActual, mainVersionExpected,
+                         "Test failed: Expected Main class version: "
+                         + mainVersionExpected + " Actual version: "
+                         + mainVersionActual);
+        assertEquals(helperVersionActual, helperVersionExpected,
+                         "Test failed: Expected Helper class version: "
+                         + helperVersionExpected + " Actual version: "
+                         + helperVersionActual);
+        assertEquals(resourceVersionActual, resourceVersionExpected,
+                         "Test failed: Expected resource version: "
+                         + resourceVersionExpected + " Actual version: "
+                         + resourceVersionActual);
+    }
+
+    @Test(dataProvider = "jarFiles")
+    void testJjs(String jar, int mainVer, int helperVer, int resVer)
+            throws Throwable {
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jjs");
+        launcher.addToolArg("-cp").addToolArg(jar)
+                .addToolArg(src + "/data/runtimetest/MVJarJJSTestScript.js");
+        ProcessTools.executeCommand(launcher.getCommand())
+                .shouldHaveExitValue(SUCCESS)
+                .shouldContain("Main version: " + mainVer)
+                .shouldContain("Helpers version: " + helperVer)
+                .shouldContain("Resource version: " + resVer);
+    }
+
+    private static OutputAnalyzer jar(String... args) throws Throwable {
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar");
+        Stream.of(args).forEach(launcher::addToolArg);
+        return ProcessTools.executeCommand(launcher.getCommand());
+    }
+
+    private void compile() throws Throwable {
+        String[] vers = { "base", "v9", "v10" };
+        for (String ver : vers) {
+            Path classes = Paths.get(usr, "classes", ver);
+            Files.createDirectories(classes);
+            Path source = Paths.get(src, "data", "runtimetest", ver);
+            assertTrue(CompilerUtils.compile(source, classes));
+            Files.copy(source.resolve("versionResource"),
+                    classes.resolve("versionResource"),
+                    StandardCopyOption.REPLACE_EXISTING);
+        }
+
+        Path classes = Paths.get(usr, "classes", "test");
+        Files.createDirectory(classes);
+        Path source = Paths.get(src, "data", "runtimetest", "test");
+        assertTrue(
+                CompilerUtils.compile(source, classes, "-cp", "classes/base/"));
+        Files.copy(Paths.get(src, "data", "runtimetest", "manifest.txt"),
+                Paths.get(usr, "manifest.txt"),
+                StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    OutputAnalyzer java(String... args) throws Throwable {
+        String java = JDKToolFinder.getJDKTool("java");
+
+        List<String> commands = new ArrayList<>();
+        commands.add(java);
+        Stream.of(args).forEach(x -> commands.add(x));
+        return ProcessTools.executeCommand(new ProcessBuilder(commands));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/MVJarJJSTestScript.js	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+var Main = Java.type("testpackage.Main");
+var mainVersion = Main.getMainVersion();
+var helperVersion = Main.getHelperVersion();
+var resourceVersion = Main.getResourceVersion();
+print("Main version: " + mainVersion);
+print("Helpers version: " + helperVersion);
+print("Resource version: " + resourceVersion);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Helper.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpackage;
+
+public class Helper {
+
+    private static final int HELPER_VERSION = 8;
+
+    public static int getHelperVersion() {
+        return HELPER_VERSION;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/testpackage/Main.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpackage;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class Main {
+
+    private static final int MAIN_VERSION = 8;
+
+    public static void main(String[] args) {
+        System.out.println("Main version: " + getMainVersion());
+        System.out.println("Helpers version: " + getHelperVersion());
+        System.out.println("Resource version: " + getResourceVersion());
+    }
+
+    public static int getMainVersion() {
+        return MAIN_VERSION;
+    }
+
+    public static int getHelperVersion() {
+        return testpackage.Helper.getHelperVersion();
+    }
+
+    public static int getResourceVersion() {
+        ClassLoader cl = Main.class.getClassLoader();
+        InputStream ris = cl.getResourceAsStream("versionResource");
+        if (ris == null) {
+            throw new Error("Test issue: resource versionResource"
+                    + " cannot be loaded!");
+        }
+        try (BufferedReader br = new BufferedReader(new InputStreamReader(ris))) {
+            return Integer.parseInt(br.readLine());
+        } catch (IOException ioe) {
+            throw new Error("Unexpected issue", ioe);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/base/versionResource	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,1 @@
+8
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/manifest.txt	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,1 @@
+Main-Class: testpackage.Main
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByImport.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import testpackage.Main;
+
+/**
+ * This class is used in MVJarAsLibraryTest.java test.
+ * It is a part of the test.
+ */
+public class UseByImport {
+
+    /**
+     * Method for the test execution.
+     * @param args - no args needed
+     */
+    public static void main(String[] args) {
+        System.out.println("Main version: " + Main.getMainVersion());
+        System.out.println("Helpers version: " + Main.getHelperVersion());
+        System.out.println("Resource version: " + Main.getResourceVersion());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/test/UseByReflection.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * This class is used in RuntimeTest.java.
+ */
+public class UseByReflection {
+
+    /**
+     * Method for the test execution.
+     *
+     * @param args - no args needed
+     * @throws java.lang.ClassNotFoundException
+     * @throws java.lang.NoSuchMethodException
+     * @throws java.lang.IllegalAccessException
+     * @throws java.lang.reflect.InvocationTargetException
+     * @throws java.io.IOException
+     */
+    public static void main(String[] args) throws ClassNotFoundException,
+            NoSuchMethodException, IllegalAccessException,
+            IllegalArgumentException, InvocationTargetException, IOException {
+        Class mainClass = Class.forName("testpackage.Main");
+        Method getMainVersion = mainClass.getMethod("getMainVersion");
+        int mainVersionActual = (int) getMainVersion.invoke(null);
+        Method getHelperVersion = mainClass.getMethod("getHelperVersion");
+        int helperVersionActual = (int) getHelperVersion.invoke(null);
+        ClassLoader cl = UseByReflection.class.getClassLoader();
+        int resourceVersionActual;
+        try (InputStream ris = cl.getResourceAsStream("versionResource");
+                BufferedReader br = new BufferedReader(new InputStreamReader(ris))) {
+            resourceVersionActual = Integer.parseInt(br.readLine());
+        }
+        System.out.println("Main version: " + mainVersionActual);
+        System.out.println("Helpers version: " + helperVersionActual);
+        System.out.println("Resource version: " + resourceVersionActual);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Helper.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpackage;
+
+public class Helper {
+
+    private static final int HELPER_VERSION = 10;
+
+    public static int getHelperVersion() {
+        return HELPER_VERSION;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/testpackage/Main.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpackage;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class Main {
+
+    private static final int MAIN_VERSION = 10;
+
+    public static void main(String[] args) {
+        System.out.println("Main version: " + getMainVersion());
+        System.out.println("Helpers version: " + getHelperVersion());
+        System.out.println("Resource version: " + getResourceVersion());
+    }
+
+    public static int getMainVersion() {
+        return MAIN_VERSION;
+    }
+
+    public static int getHelperVersion() {
+        return testpackage.Helper.getHelperVersion();
+    }
+
+    public static int getResourceVersion() {
+        ClassLoader cl = Main.class.getClassLoader();
+        InputStream ris = cl.getResourceAsStream("versionResource");
+        if (ris == null) {
+            throw new Error("Test issue: resource versionResource"
+                    + " cannot be loaded!");
+        }
+        try (BufferedReader br = new BufferedReader(new InputStreamReader(ris))) {
+            return Integer.parseInt(br.readLine());
+        } catch (IOException ioe) {
+            throw new Error("Unexpected issue", ioe);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v10/versionResource	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,1 @@
+10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Helper.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpackage;
+
+public class Helper {
+
+    private static final int HELPER_VERSION = 9;
+
+    public static int getHelperVersion() {
+        return HELPER_VERSION;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/testpackage/Main.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testpackage;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class Main {
+
+    private static final int MAIN_VERSION = 9;
+
+    public static void main(String[] args) {
+        System.out.println("Main version: " + getMainVersion());
+        System.out.println("Helpers version: " + getHelperVersion());
+        System.out.println("Resource version: " + getResourceVersion());
+    }
+
+    public static int getMainVersion() {
+        return MAIN_VERSION;
+    }
+
+    public static int getHelperVersion() {
+        return testpackage.Helper.getHelperVersion();
+    }
+
+    public static int getResourceVersion() {
+        ClassLoader cl = Main.class.getClassLoader();
+        InputStream ris = cl.getResourceAsStream("versionResource");
+        if (ris == null) {
+            throw new Error("Test issue: resource versionResource"
+                    + " cannot be loaded!");
+        }
+        try (BufferedReader br = new BufferedReader(new InputStreamReader(ris))) {
+            return Integer.parseInt(br.readLine());
+        } catch (IOException ioe) {
+            throw new Error("Unexpected issue", ioe);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/multiRelease/data/runtimetest/v9/versionResource	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,1 @@
+9
--- a/jdk/test/tools/jmod/JmodTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/tools/jmod/JmodTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8142968 8166568 8166286 8170618
+ * @bug 8142968 8166568 8166286 8170618 8168149
  * @summary Basic test for jmod
  * @library /lib/testlibrary
  * @modules jdk.compiler
@@ -459,6 +459,76 @@
     }
 
     @Test
+    public void testLastOneWins() throws IOException {
+        Path workDir = Paths.get("lastOneWins");
+        if (Files.exists(workDir))
+            FileUtils.deleteFileTreeWithRetry(workDir);
+        Files.createDirectory(workDir);
+        Path jmod = MODS_DIR.resolve("lastOneWins.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        Path cp = EXPLODED_DIR.resolve("foo").resolve("classes");
+        Path bp = EXPLODED_DIR.resolve("foo").resolve("bin");
+        Path lp = EXPLODED_DIR.resolve("foo").resolve("lib");
+        Path cf = EXPLODED_DIR.resolve("foo").resolve("conf");
+
+        Path shouldNotBeAdded = workDir.resolve("shouldNotBeAdded");
+        Files.createDirectory(shouldNotBeAdded);
+        Files.write(shouldNotBeAdded.resolve("aFile"), "hello".getBytes(UTF_8));
+
+        // Pairs of options. For options with required arguments the last one
+        // should win ( first should be effectively ignored, but may still be
+        // validated ).
+        jmod("create",
+             "--conf", shouldNotBeAdded.toString(),
+             "--conf", cf.toString(),
+             "--cmds", shouldNotBeAdded.toString(),
+             "--cmds", bp.toString(),
+             "--libs", shouldNotBeAdded.toString(),
+             "--libs", lp.toString(),
+             "--class-path", shouldNotBeAdded.toString(),
+             "--class-path", cp.toString(),
+             "--main-class", "does.NotExist",
+             "--main-class", "jdk.test.foo.Foo",
+             "--module-version", "00001",
+             "--module-version", "5.4.3",
+             "--do-not-resolve-by-default",
+             "--do-not-resolve-by-default",
+             "--warn-if-resolved=incubating",
+             "--warn-if-resolved=deprecated",
+             MODS_DIR.resolve("lastOneWins.jmod").toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                ModuleDescriptor md = getModuleDescriptor(jmod);
+                Optional<String> omc = md.mainClass();
+                assertTrue(omc.isPresent());
+                assertEquals(omc.get(), "jdk.test.foo.Foo");
+                Optional<Version> ov = md.version();
+                assertTrue(ov.isPresent());
+                assertEquals(ov.get().toString(), "5.4.3");
+
+                try (Stream<String> s1 = findFiles(lp).map(p -> LIBS_PREFIX + p);
+                     Stream<String> s2 = findFiles(cp).map(p -> CLASSES_PREFIX + p);
+                     Stream<String> s3 = findFiles(bp).map(p -> CMDS_PREFIX + p);
+                     Stream<String> s4 = findFiles(cf).map(p -> CONFIGS_PREFIX + p)) {
+                    Set<String> expectedFilenames = Stream.concat(Stream.concat(s1,s2),
+                                                                  Stream.concat(s3, s4))
+                                                          .collect(toSet());
+                    assertJmodContent(jmod, expectedFilenames);
+                }
+            });
+
+        jmod("extract",
+             "--dir", "blah",
+             "--dir", "lastOneWinsExtractDir",
+             jmod.toString())
+            .assertSuccess()
+            .resultChecker(r -> {
+                assertTrue(Files.exists(Paths.get("lastOneWinsExtractDir")));
+                assertTrue(Files.notExists(Paths.get("blah")));
+            });
+    }
+
+    @Test
     public void testPackagesAttribute() throws IOException {
         Path jmod = MODS_DIR.resolve("foo.jmod");
         FileUtils.deleteFileIfExistsWithRetry(jmod);
@@ -510,36 +580,24 @@
     }
 
     @Test
-    public void testTmpFileAlreadyExists() throws IOException {
-        // Implementation detail: jmod tool creates <jmod-file>.tmp
-        // Ensure that there are no problems if existing
-
-        Path jmod = MODS_DIR.resolve("testTmpFileAlreadyExists.jmod");
-        Path tmp = MODS_DIR.resolve("testTmpFileAlreadyExists.jmod.tmp");
-        FileUtils.deleteFileIfExistsWithRetry(jmod);
-        FileUtils.deleteFileIfExistsWithRetry(tmp);
-        Files.createFile(tmp);
-        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
-
-        jmod("create",
-             "--class-path", cp,
-             jmod.toString())
-            .assertSuccess()
-            .resultChecker(r ->
-                assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp)
-            );
-    }
-
-    @Test
     public void testTmpFileRemoved() throws IOException {
         // Implementation detail: jmod tool creates <jmod-file>.tmp
         // Ensure that it is removed in the event of a failure.
         // The failure in this case is a class in the unnamed package.
 
-        Path jmod = MODS_DIR.resolve("testTmpFileRemoved.jmod");
-        Path tmp = MODS_DIR.resolve("testTmpFileRemoved.jmod.tmp");
+        String filename = "testTmpFileRemoved.jmod";
+        Path jmod = MODS_DIR.resolve(filename);
+
+        // clean up files
         FileUtils.deleteFileIfExistsWithRetry(jmod);
-        FileUtils.deleteFileIfExistsWithRetry(tmp);
+        findTmpFiles(filename).forEach(tmp -> {
+            try {
+                FileUtils.deleteFileIfExistsWithRetry(tmp);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        });
+
         String cp = EXPLODED_DIR.resolve("foo").resolve("classes") + File.pathSeparator +
                     EXPLODED_DIR.resolve("foo").resolve("classes")
                                 .resolve("jdk").resolve("test").resolve("foo").toString();
@@ -550,10 +608,22 @@
              .assertFailure()
              .resultChecker(r -> {
                  assertContains(r.output, "unnamed package");
-                 assertTrue(Files.notExists(tmp), "Unexpected tmp file:" + tmp);
+                 Set<Path> tmpfiles = findTmpFiles(filename).collect(toSet());
+                 assertTrue(tmpfiles.isEmpty(), "Unexpected tmp file:" + tmpfiles);
              });
     }
 
+    private Stream<Path> findTmpFiles(String prefix) {
+        try {
+            Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));
+            return Files.find(tmpdir, 1, (p, attrs) ->
+                p.getFileName().toString().startsWith(prefix)
+                    && p.getFileName().toString().endsWith(".tmp"));
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
     // ---
 
     static boolean compileModule(String name, Path dest) throws IOException {
--- a/jdk/test/tools/jmod/hashes/HashesTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/jdk/test/tools/jmod/hashes/HashesTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * 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,19 +23,22 @@
 
 /*
  * @test
+ * @bug 8160286
  * @summary Test the recording and checking of module hashes
- * @author Andrei Eremeev
  * @library /lib/testlibrary
  * @modules java.base/jdk.internal.misc
  *          java.base/jdk.internal.module
+ *          jdk.compiler
+ *          jdk.jartool
  *          jdk.jlink
- *          jdk.compiler
- * @build CompilerUtils
+ * @build CompilerUtils ModuleInfoMaker
  * @run testng HashesTest
  */
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
@@ -53,109 +56,311 @@
 import java.util.Set;
 import java.util.spi.ToolProvider;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import jdk.internal.module.ModuleInfo;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModulePath;
 
-import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
 import static org.testng.Assert.*;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
 
 public class HashesTest {
     static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
         .orElseThrow(() ->
             new RuntimeException("jmod tool not found")
         );
+    static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+        .orElseThrow(() ->
+            new RuntimeException("jar tool not found")
+        );
 
-    private final Path testSrc = Paths.get(System.getProperty("test.src"));
-    private final Path modSrc = testSrc.resolve("src");
-    private final Path mods = Paths.get("mods");
-    private final Path jmods = Paths.get("jmods");
-    private final String[] modules = new String[] { "m1", "m2", "m3"};
+    private final Path mods;
+    private final Path srcDir;
+    private final Path lib;
+    private final ModuleInfoMaker builder;
+    HashesTest(Path dest) throws IOException {
+        if (Files.exists(dest)) {
+            deleteDirectory(dest);
+        }
+        this.mods = dest.resolve("mods");
+        this.srcDir = dest.resolve("src");
+        this.lib = dest.resolve("lib");
+        this.builder = new ModuleInfoMaker(srcDir);
+
+        Files.createDirectories(lib);
+        Files.createDirectories(mods);
+    }
+
+    @Test
+    public static void test() throws IOException {
+        Path dest = Paths.get("test");
+        HashesTest ht = new HashesTest(dest);
 
-    @BeforeTest
-    private void setup() throws Exception {
-        if (Files.exists(jmods)) {
-            deleteDirectory(jmods);
-        }
-        Files.createDirectories(jmods);
+        // create modules for test cases
+        ht.makeModule("m2");
+        ht.makeModule("m3");
+        ht.makeModule("m1", "m2", "m3");
+
+        ht.makeModule("org.bar", TRANSITIVE, "m1");
+        ht.makeModule("org.foo", TRANSITIVE, "org.bar");
+
+        // create JMOD for m1, m2, m3
+        ht.makeJmod("m2");
+        ht.makeJmod("m3");
+
+        // no hash is recorded since m1 has outgoing edges
+        ht.jmodHashModules("m1", ".*");
+
+        // no hash is recorded in m1, m2, m3
+        assertTrue(ht.hashes("m1") == null);
+        assertTrue(ht.hashes("m2") == null);
+        assertTrue(ht.hashes("m3") == null);
+
+        // hash m1 in m2
+        ht.jmodHashModules("m2",  "m1");
+        ht.checkHashes("m2", "m1");
+
+        // hash m1 in m2
+        ht.jmodHashModules("m2",  ".*");
+        ht.checkHashes("m2", "m1");
 
-        // build m2, m3 required by m1
-        compileModule("m2", modSrc);
-        jmod("m2");
+        // create m2.jmod with no hash
+        ht.makeJmod("m2");
+        // run jmod hash command to hash m1 in m2 and m3
+        runJmod(List.of("hash", "--module-path", ht.lib.toString(),
+                        "--hash-modules", ".*"));
+        ht.checkHashes("m2", "m1");
+        ht.checkHashes("m3", "m1");
+
+        // check transitive requires
+        ht.makeJmod("org.bar");
+        ht.makeJmod("org.foo");
 
-        compileModule("m3", modSrc);
-        jmod("m3");
+        ht.jmodHashModules("org.bar", "org.*");
+        ht.checkHashes("org.bar", "org.foo");
+
+        ht.jmodHashModules( "m3", ".*");
+        ht.checkHashes("m3", "org.foo", "org.bar", "m1");
+    }
+
+    @Test
+    public static void multiBaseModules() throws IOException {
+        Path dest = Paths.get("test2");
+        HashesTest ht = new HashesTest(dest);
 
-        // build m1
-        compileModule("m1", modSrc);
-        // no hash is recorded since m1 has outgoing edges
-        jmod("m1", "--module-path", jmods.toString(), "--hash-modules", ".*");
+        /*
+         * y2 -----------> y1
+         *    |______
+         *    |      |
+         *    V      V
+         *    z3 -> z2
+         *    |      |
+         *    |      V
+         *    |---> z1
+         */
+
+        ht.makeModule("z1");
+        ht.makeModule("z2", "z1");
+        ht.makeModule("z3", "z1", "z2");
+
+        ht.makeModule("y1");
+        ht.makeModule("y2", "y1", "z2", "z3");
 
-        // compile org.bar and org.foo
-        compileModule("org.bar", modSrc);
-        compileModule("org.foo", modSrc);
+        Set<String> ys = Set.of("y1", "y2");
+        Set<String> zs = Set.of("z1", "z2", "z3");
+
+        // create JMOD files
+        Stream.concat(ys.stream(), zs.stream()).forEach(ht::makeJmod);
+
+        // run jmod hash command
+        runJmod(List.of("hash", "--module-path", ht.lib.toString(),
+                        "--hash-modules", ".*"));
+
+        /*
+         * z1 and y1 are the modules with hashes recorded.
+         */
+        ht.checkHashes("y1", "y2");
+        ht.checkHashes("z1", "z2", "z3", "y2");
+        Stream.concat(ys.stream(), zs.stream())
+              .filter(mn -> !mn.equals("y1") && !mn.equals("z1"))
+              .forEach(mn -> assertTrue(ht.hashes(mn) == null));
     }
 
     @Test
-    public void test() throws Exception {
-        for (String mn : modules) {
-            assertTrue(hashes(mn) == null);
+    public static void mixJmodAndJarFile() throws IOException {
+        Path dest = Paths.get("test3");
+        HashesTest ht = new HashesTest(dest);
+
+        /*
+         * j3 -----------> j2
+         *    |______
+         *    |      |
+         *    V      V
+         *    m3 -> m2
+         *    |      |
+         *    |      V
+         *    |---> m1 -> j1 -> jdk.jlink
+         */
+
+        ht.makeModule("j1");
+        ht.makeModule("j2");
+        ht.makeModule("m1", "j1");
+        ht.makeModule("m2", "m1");
+        ht.makeModule("m3", "m1", "m2");
+
+        ht.makeModule("j3", "j2", "m2", "m3");
+
+        Set<String> jars = Set.of("j1", "j2", "j3");
+        Set<String> jmods = Set.of("m1", "m2", "m3");
+
+        // create JMOD and JAR files
+        jars.forEach(ht::makeJar);
+        jmods.forEach(ht::makeJmod);
+
+        // run jmod hash command
+        runJmod(List.of("hash", "--module-path", ht.lib.toString(),
+                        "--hash-modules", "^j.*|^m.*"));
+
+        /*
+         * j1 and j2 are the modules with hashes recorded.
+         */
+        ht.checkHashes("j2", "j3");
+        ht.checkHashes("j1", "m1", "m2", "m3", "j3");
+        Stream.concat(jars.stream(), jmods.stream())
+              .filter(mn -> !mn.equals("j1") && !mn.equals("j2"))
+              .forEach(mn -> assertTrue(ht.hashes(mn) == null));
+    }
+
+    @Test
+    public static void upgradeableModule() throws IOException {
+        Path mpath = Paths.get(System.getProperty("java.home"), "jmods");
+        if (!Files.exists(mpath)) {
+            return;
         }
 
-        // hash m1 in m2
-        jmod("m2", "--module-path", jmods.toString(), "--hash-modules", "m1");
-        checkHashes(hashes("m2"), "m1");
-
-        // hash m1 in m2
-        jmod("m2", "--module-path", jmods.toString(), "--hash-modules", ".*");
-        checkHashes(hashes("m2"), "m1");
+        Path dest = Paths.get("test4");
+        HashesTest ht = new HashesTest(dest);
+        ht.makeModule("m1");
+        ht.makeModule("java.xml.bind", "m1");
+        ht.makeModule("java.xml.ws", "java.xml.bind");
+        ht.makeModule("m2", "java.xml.ws");
 
-        // create m2.jmod with no hash
-        jmod("m2");
-        // run jmod hash command to hash m1 in m2 and m3
-        runJmod(Arrays.asList("hash", "--module-path", jmods.toString(),
-                "--hash-modules", ".*"));
-        checkHashes(hashes("m2"), "m1");
-        checkHashes(hashes("m3"), "m1");
+        ht.makeJmod("m1");
+        ht.makeJmod("m2");
+        ht.makeJmod("java.xml.ws");
+        ht.makeJmod("java.xml.bind",
+                    "--module-path",
+                    ht.lib.toString() + File.pathSeparator + mpath,
+                    "--hash-modules", "^java.xml.*|^m.*");
 
-        jmod("org.bar");
-        jmod("org.foo");
-
-        jmod("org.bar", "--module-path", jmods.toString(), "--hash-modules", "org.*");
-        checkHashes(hashes("org.bar"), "org.foo");
-
-        jmod("m3", "--module-path", jmods.toString(), "--hash-modules", ".*");
-        checkHashes(hashes("m3"), "org.foo", "org.bar", "m1");
+        ht.checkHashes("java.xml.bind", "java.xml.ws", "m2");
     }
 
-    private void checkHashes(ModuleHashes hashes, String... hashModules) {
+    @Test
+    public static void testImageJmods() throws IOException {
+        Path mpath = Paths.get(System.getProperty("java.home"), "jmods");
+        if (!Files.exists(mpath)) {
+            return;
+        }
+
+        Path dest = Paths.get("test5");
+        HashesTest ht = new HashesTest(dest);
+        ht.makeModule("m1", "jdk.compiler", "jdk.attach");
+        ht.makeModule("m2", "m1");
+        ht.makeModule("m3", "java.compiler");
+
+        ht.makeJmod("m1");
+        ht.makeJmod("m2");
+
+        runJmod(List.of("hash",
+                        "--module-path",
+                        mpath.toString() + File.pathSeparator + ht.lib.toString(),
+                        "--hash-modules", ".*"));
+
+        validateImageJmodsTest(ht, mpath);
+    }
+
+    @Test
+    public static void testImageJmods1() throws IOException {
+        Path mpath = Paths.get(System.getProperty("java.home"), "jmods");
+        if (!Files.exists(mpath)) {
+            return;
+        }
+
+        Path dest = Paths.get("test6");
+        HashesTest ht = new HashesTest(dest);
+        ht.makeModule("m1", "jdk.compiler", "jdk.attach");
+        ht.makeModule("m2", "m1");
+        ht.makeModule("m3", "java.compiler");
+
+        ht.makeJar("m2");
+        ht.makeJar("m1",
+                    "--module-path",
+                    mpath.toString() + File.pathSeparator + ht.lib.toString(),
+                    "--hash-modules", ".*");
+        validateImageJmodsTest(ht, mpath);
+    }
+
+    private static void validateImageJmodsTest(HashesTest ht, Path mpath)
+        throws IOException
+    {
+        // hash is recorded in m1 and not any other packaged modules on module path
+        ht.checkHashes("m1", "m2");
+        assertTrue(ht.hashes("m2") == null);
+
+        // should not override any JDK packaged modules
+        ModuleFinder finder = new ModulePath(Runtime.version(),
+                                             true,
+                                             mpath);
+        assertTrue(ht.hashes(finder,"jdk.compiler") == null);
+        assertTrue(ht.hashes(finder,"jdk.attach") == null);
+    }
+
+    private void checkHashes(String mn, String... hashModules) throws IOException {
+        ModuleHashes hashes = hashes(mn);
         assertTrue(hashes.names().equals(Set.of(hashModules)));
     }
 
-    private ModuleHashes hashes(String name) throws Exception {
+    private ModuleHashes hashes(String name) {
         ModuleFinder finder = new ModulePath(Runtime.version(),
                                              true,
-                                             jmods.resolve(name + ".jmod"));
+                                             lib);
+        return hashes(finder, name);
+    }
+
+    private ModuleHashes hashes(ModuleFinder finder, String name) {
         ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new);
-        ModuleReader reader = mref.open();
-        try (InputStream in = reader.open("module-info.class").get()) {
-            ModuleHashes hashes = ModuleInfo.read(in, null).recordedHashes();
-            System.out.format("hashes in module %s %s%n", name,
+        try {
+            ModuleReader reader = mref.open();
+            try (InputStream in = reader.open("module-info.class").get()) {
+                ModuleHashes hashes = ModuleInfo.read(in, null).recordedHashes();
+                System.out.format("hashes in module %s %s%n", name,
                     (hashes != null) ? "present" : "absent");
-            if (hashes != null) {
-                hashes.names().stream()
-                    .sorted()
-                    .forEach(n -> System.out.format("  %s %s%n", n, hashes.hashFor(n)));
+                if (hashes != null) {
+                    hashes.names().stream().sorted().forEach(n ->
+                        System.out.format("  %s %s%n", n, toHex(hashes.hashFor(n)))
+                    );
+                }
+                return hashes;
+            } finally {
+                reader.close();
             }
-            return hashes;
-        } finally {
-            reader.close();
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
         }
     }
 
+    private String toHex(byte[] ba) {
+        StringBuilder sb = new StringBuilder(ba.length);
+        for (byte b: ba) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
     private void deleteDirectory(Path dir) throws IOException {
         Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
             @Override
@@ -176,31 +381,94 @@
         });
     }
 
+
+    private void makeModule(String mn, String... deps) throws IOException {
+        makeModule(mn, null, deps);
+    }
+
+    private void makeModule(String mn, ModuleDescriptor.Requires.Modifier mod,  String... deps)
+        throws IOException
+    {
+        if (mod != null && mod != TRANSITIVE && mod != STATIC) {
+            throw new IllegalArgumentException(mod.toString());
+        }
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("module " + mn + " {").append("\n");
+        Arrays.stream(deps).forEach(req -> {
+            sb.append("    requires ");
+            if (mod != null) {
+                sb.append(mod.toString().toLowerCase()).append(" ");
+            }
+            sb.append(req + ";\n");
+        });
+        sb.append("}\n");
+        builder.writeJavaFiles(mn, sb.toString());
+
+        compileModule(mn, srcDir);
+    }
+
     private void compileModule(String moduleName, Path src) throws IOException {
         Path msrc = src.resolve(moduleName);
         assertTrue(CompilerUtils.compile(msrc, mods, "--module-source-path", src.toString()));
     }
 
-    private void jmod(String moduleName, String... options) throws IOException {
+    private void jmodHashModules(String moduleName, String hashModulesPattern) {
+        makeJmod(moduleName, "--module-path", lib.toString(),
+                 "--hash-modules", hashModulesPattern);
+    }
+
+    private void makeJmod(String moduleName, String... options) {
         Path mclasses = mods.resolve(moduleName);
-        Path outfile = jmods.resolve(moduleName + ".jmod");
+        Path outfile = lib.resolve(moduleName + ".jmod");
         List<String> args = new ArrayList<>();
         args.add("create");
         Collections.addAll(args, options);
         Collections.addAll(args, "--class-path", mclasses.toString(),
                            outfile.toString());
 
-        if (Files.exists(outfile))
-            Files.delete(outfile);
-
+        if (Files.exists(outfile)) {
+            try {
+                Files.delete(outfile);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
         runJmod(args);
     }
 
-    private void runJmod(List<String> args) {
+    private static void runJmod(List<String> args) {
         int rc = JMOD_TOOL.run(System.out, System.out, args.toArray(new String[args.size()]));
-        System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" ")));
+        System.out.println("jmod " + args.stream().collect(Collectors.joining(" ")));
         if (rc != 0) {
-            throw new AssertionError("Jmod failed: rc = " + rc);
+            throw new AssertionError("jmod failed: rc = " + rc);
+        }
+    }
+
+    private void makeJar(String moduleName, String... options) {
+        Path mclasses = mods.resolve(moduleName);
+        Path outfile = lib.resolve(moduleName + ".jar");
+        List<String> args = new ArrayList<>();
+        Stream.concat(Stream.of("--create",
+                                "--file=" + outfile.toString()),
+                      Arrays.stream(options))
+              .forEach(args::add);
+        args.add("-C");
+        args.add(mclasses.toString());
+        args.add(".");
+
+        if (Files.exists(outfile)) {
+            try {
+                Files.delete(outfile);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        }
+
+        int rc = JAR_TOOL.run(System.out, System.out, args.toArray(new String[args.size()]));
+        System.out.println("jar " + args.stream().collect(Collectors.joining(" ")));
+        if (rc != 0) {
+            throw new AssertionError("jar failed: rc = " + rc);
         }
     }
 }
--- a/jdk/test/tools/jmod/hashes/src/m1/module-info.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m1 {
-    requires m2;
-    requires m3;
-}
--- a/jdk/test/tools/jmod/hashes/src/m1/org/m1/Main.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m1;
-
-import org.m2.Util;
-import org.m3.Name;
-
-public class Main {
-    public static void main(String[] args) {
-        System.out.println(Util.timeOfDay());
-        System.out.println(Name.name());
-    }
-}
--- a/jdk/test/tools/jmod/hashes/src/m2/module-info.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m2 {
-    exports org.m2;
-}
--- a/jdk/test/tools/jmod/hashes/src/m2/org/m2/Util.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m2;
-
-public class Util {
-    private Util() { }
-
-    public static String timeOfDay() {
-        return "Time for lunch";
-    }
-}
--- a/jdk/test/tools/jmod/hashes/src/m3/module-info.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m3 {
-    exports org.m3;
-}
--- a/jdk/test/tools/jmod/hashes/src/m3/org/m3/Name.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org.m3;
-
-public class Name {
-    private Name() { }
-
-    public static String name() {
-        return "m3";
-    }
-}
--- a/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +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.
- *
- * This code is distributed in the hope that it 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.
- */
-
-module org.bar {
-    requires transitive m1;
-}
--- a/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java	Tue Jan 17 07:41:04 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +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.
- *
- * This code is distributed in the hope that it 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.
- */
-
-module org.foo {
-    requires transitive org.bar;
-}
--- a/make/Bundles.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/Bundles.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -77,9 +77,8 @@
 	$$(call MakeDir, $$(@D))
         ifneq ($$($1_SPECIAL_INCLUDES), )
 	  $$(foreach i, $$($1_SPECIAL_INCLUDES), \
-	    $$(foreach d, $$d, \
-	      ($(CD) $$d && $(FIND) $$i \
-	          >> $(SUPPORT_OUTPUTDIR)/bundles/_$1_files ) ; ))
+	    $$(foreach d, $$($1_BASE_DIRS), \
+	      ($(CD) $$d && $(FIND) $$i >> $$($1_$$d_LIST_FILE)) ; ))
         endif
         ifeq ($$($1_SUBDIR)-$$($1_TYPE)-$$($1_UNZIP_DEBUGINFO), .-zip-false)
           # If no subdir is specified, zip can be done directly from BASE_DIRS.
@@ -152,6 +151,9 @@
   JRE_IMAGE_HOMEDIR := $(JRE_IMAGE_DIR)
   JDK_BUNDLE_SUBDIR := jdk-$(VERSION_NUMBER)
   JRE_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER)
+  JRE_COMPACT1_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER)-compact1
+  JRE_COMPACT2_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER)-compact2
+  JRE_COMPACT3_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER)-compact3
   ifneq ($(DEBUG_LEVEL), release)
     JDK_BUNDLE_SUBDIR := $(JDK_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
     JRE_BUNDLE_SUBDIR := $(JRE_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
@@ -281,6 +283,35 @@
 
 ################################################################################
 
+ifneq ($(filter profiles-bundles, $(MAKECMDGOALS)), )
+  ifeq ($(OPENJDK_TARGET_OS), macosx)
+    $(error Creating compact profiles bundles on macosx is unsupported)
+  endif
+
+  define GenerateCompactProfilesBundles
+    ALL_JRE_COMPACT$1_FILES := $$(call CacheFind, $$(JRE_COMPACT$1_IMAGE_DIR))
+
+    JRE_COMPACT$1_BUNDLE_FILES := $$(filter-out \
+        $$(SYMBOLS_EXCLUDE_PATTERN), \
+        $$(ALL_JRE_COMPACT$1_FILES))
+
+    $$(eval $$(call SetupBundleFile, BUILD_JRE_COMPACT$1_BUNDLE, \
+        BUNDLE_NAME := $$(JRE_COMPACT$1_BUNDLE_NAME), \
+        FILES := $$(JRE_COMPACT$1_BUNDLE_FILES), \
+        BASE_DIRS := $$(JRE_COMPACT$1_IMAGE_DIR), \
+        SUBDIR := $$(JRE_COMPACT$1_BUNDLE_SUBDIR), \
+    ))
+
+    PROFILES_TARGETS += $$(BUILD_JRE_COMPACT$1_BUNDLE)
+  endef
+
+  $(eval $(call GenerateCompactProfilesBundles,1))
+  $(eval $(call GenerateCompactProfilesBundles,2))
+  $(eval $(call GenerateCompactProfilesBundles,3))
+endif
+
+################################################################################
+
 ifneq ($(filter test-bundles, $(MAKECMDGOALS)), )
   TEST_BUNDLE_FILES := $(call CacheFind, $(TEST_IMAGE_DIR))
 
@@ -316,7 +347,8 @@
 ################################################################################
 
 product-bundles: $(PRODUCT_TARGETS)
+profiles-bundles: $(PROFILES_TARGETS)
 test-bundles: $(TEST_TARGETS)
 docs-bundles: $(DOCS_TARGETS)
 
-.PHONY: all default product-bundles test-bundles docs-bundles
+.PHONY: all default product-bundles profiles-bundles test-bundles docs-bundles
--- a/make/CompileJavaModules.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/CompileJavaModules.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -383,6 +383,10 @@
 
 ################################################################################
 
+jdk.jartool_ADD_JAVAC_FLAGS := -XDstringConcat=inline
+
+################################################################################
+
 jdk.rmic_SETUP := GENERATE_JDKBYTECODE_NOWARNINGS
 jdk.rmic_CLEAN := .properties
 
--- a/make/Images.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/Images.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -147,10 +147,6 @@
 	    --output $(JRE_IMAGE_DIR)
 	$(TOUCH) $@
 
-JRE_COMPACT1_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact1
-JRE_COMPACT2_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact2
-JRE_COMPACT3_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact3
-
 
 $(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
     $(call DependOnVariable, JRE_COMPACT1_MODULES_LIST) $(BASE_RELEASE_FILE)
--- a/make/Javadoc.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/Javadoc.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -1,4 +1,4 @@
-# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -86,7 +86,7 @@
     DRAFT_WINDOW_TITLE_MARKER := $(SPACE)[build $(VERSION_BUILD)]
   endif
   EARLYACCESS_TOP := \
-      <div style="background-color: $$(HASH)EEEEEE"><div style="padding: 6px; \
+      <div style="background-color: $(HASH)EEEEEE"><div style="padding: 6px; \
       margin-top: 2px; margin-bottom: 6px; margin-left: 6px; margin-right: \
       6px; text-align: justify; font-size: 80%; font-family: Helvetica, Arial, \
       sans-serif; font-weight: normal;">Please note that the specifications \
@@ -235,10 +235,6 @@
 
   $1_OPTIONS += --add-modules $$(call CommaList, $$($1_MODULES))
 
-  ifneq ($$(LOG_LEVEL), trace)
-    $1_OPTIONS += -quiet
-  endif
-
   ifneq ($$($1_DISABLED_DOCLINT), )
     # Create a string like ",-syntax,-html"
     $1_DOCLINT_EXCEPTIONS := ,$$(call CommaList, $$(addprefix -, $$($1_DISABLED_DOCLINT)))
@@ -292,6 +288,13 @@
   $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
        $$(SUPPORT_OUTPUTDIR)/docs/$1.vardeps)
 
+  # Do not store debug level options in VARDEPS.
+  ifneq ($$(LOG_LEVEL), trace)
+    $1_OPTIONS += -quiet
+  else
+    $1_OPTIONS += -verbose
+  endif
+
   $1_PACKAGE_DEPS := $$(call CacheFind, $$(wildcard $$(foreach p, \
       $$(subst .,/,$$(strip $$($1_PACKAGES))), \
       $$(addsuffix /$$p, $$(wildcard $$(JAVADOC_SOURCE_DIRS))))))
--- a/make/Main.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/Main.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -342,7 +342,7 @@
 symbols-image:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Images.gmk symbols)
 
-profiles:
+profiles-image:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Images.gmk profiles)
 
 mac-bundles-jdk:
@@ -356,7 +356,7 @@
 
 ALL_TARGETS += store-source-revision create-source-revision-tracker bootcycle-images zip-security \
     zip-source jrtfs-jar jdk-image jre-image \
-    symbols-image profiles mac-bundles-jdk \
+    symbols-image profiles-image mac-bundles-jdk \
     release-file exploded-image-optimize
 
 ################################################################################
@@ -510,13 +510,16 @@
 product-bundles:
 	+($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk product-bundles)
 
+profiles-bundles:
+	+($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk profiles-bundles)
+
 test-bundles:
 	+($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk test-bundles)
 
 docs-bundles:
 	+($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f Bundles.gmk docs-bundles)
 
-ALL_TARGETS += product-bundles test-bundles docs-bundles
+ALL_TARGETS += product-bundles profiles-bundles test-bundles docs-bundles
 
 ################################################################################
 # Install targets
@@ -734,7 +737,7 @@
   jre-image: jmods release-file
   symbols-image: $(LIBS_TARGETS) $(LAUNCHER_TARGETS)
 
-  profiles: jmods release-file
+  profiles-image: jmods release-file
 
   mac-bundles-jdk: jdk-image jre-image
 
@@ -793,6 +796,8 @@
 
   product-bundles: product-images
 
+  profiles-bundles: profiles-images
+
   test-bundles: test-image
 
   docs-bundles: docs-image
@@ -878,6 +883,9 @@
 # an image until this can be cleaned up properly.
 product-images: zip-security
 
+# Declare these for backwards compatiblity and convenience.
+profiles profiles-images: profiles-image
+
 # The module summary cannot be run when:
 # * Cross compiling and building a partial BUILDJDK for the build host
 # * An external buildjdk has been supplied since it may not match the
@@ -909,7 +917,9 @@
     copy java rmic libs launchers jmods \
     jdk.jdwp.agent-gensrc $(ALL_MODULES) demos samples \
     exploded-image-base exploded-image \
-    create-buildjdk mac-bundles product-images docs-image test-image all-images \
+    create-buildjdk mac-bundles product-images \
+    profiles profiles-images \
+    docs-image test-image all-images \
     all-bundles
 
 ################################################################################
--- a/make/common/MakeBase.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/common/MakeBase.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -435,7 +435,7 @@
       Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk))
   # Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix
   $(foreach i,$(PARAM_SEQUENCE), $(if $(strip $($i)),\
-    $(strip $1)_$(strip $(call DoubleDollar, $($i))))$(NEWLINE))
+    $(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE)))
   # Debug print all named parameter names and values
   $(if $(findstring $(LOG_LEVEL),debug trace), \
     $(info $0 $(strip $1) $(foreach i,$(PARAM_SEQUENCE), \
--- a/make/common/NativeCompilation.gmk	Tue Jan 17 07:41:04 2017 +0100
+++ b/make/common/NativeCompilation.gmk	Wed Jul 05 22:42:01 2017 +0200
@@ -288,8 +288,7 @@
         $$($1_$(notdir $2)_OPTIMIZATION)), )
       $1_$2_VARDEPS := $$($1_$(notdir $2)_CFLAGS) $$($1_$(notdir $2)_CXXFLAGS) \
           $$($1_$(notdir $2)_OPT_CFLAGS) $$($1_$(notdir $2)_OPT_CXXFLAGS)
-      $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \
-          $$(patsubst %$(OBJ_SUFFIX),%.vardeps,$$($1_$2_OBJ)))
+      $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, $$($1_$2_OBJ).vardeps)
     endif
 
     $$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) $$($1_$2_VARDEPS_FILE) | $$($1_BUILD_INFO)
--- a/nashorn/.hgtags	Tue Jan 17 07:41:04 2017 +0100
+++ b/nashorn/.hgtags	Wed Jul 05 22:42:01 2017 +0200
@@ -385,3 +385,4 @@
 c281306d33d83c92e0d870ace385d5f99678d7e7 jdk-9+149
 ace1d994bca775d6545a4c874ae73d1dfc9ec18b jdk-9+150
 2a0437036a64853334e538044eb68d2df70075fa jdk-9+151
+ddc52e72757086a75a54371e8e7f56a3f89f1e55 jdk-9+152
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Jul 05 22:42:01 2017 +0200
@@ -1032,7 +1032,7 @@
             }
 
             final Object key = property.getKey();
-            property = iter.next();
+            property = iter.hasNext() ? iter.next() : null;
             skipNotEnumerable();
 
             return key;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Jul 05 22:42:01 2017 +0200
@@ -28,6 +28,8 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -100,7 +102,7 @@
      * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe
      * to be cleared as they can be reparsed).
      */
-    private volatile Object cachedAst;
+    private volatile transient Object cachedAst;
 
     /** Token of this function within the source. */
     private final long token;
@@ -289,6 +291,9 @@
         if (this.source == null && this.installer == null) {
             this.source    = src;
             this.installer = inst;
+            for (final RecompilableScriptFunctionData nested : nestedFunctions.values()) {
+                nested.initTransients(src, inst);
+            }
         } else if (this.source != src || !this.installer.isCompatibleWith(inst)) {
             // Existing values must be same as those passed as parameters
             throw new IllegalArgumentException();
@@ -424,7 +429,7 @@
         } else if (lCachedAst instanceof SerializedAst) {
             final SerializedAst serializedAst = (SerializedAst)lCachedAst;
             // Even so, are we also softly caching the AST?
-            final FunctionNode cachedFn = serializedAst.cachedAst.get();
+            final FunctionNode cachedFn = serializedAst.cachedAst == null ? null : serializedAst.cachedAst.get();
             if (cachedFn != null) {
                 // Yes we are - this is fast
                 return cloneSymbols(cachedFn);
@@ -492,9 +497,11 @@
      * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on
      * deserialization costs.
      */
-    private static class SerializedAst {
+    private static class SerializedAst implements Serializable {
         private final byte[] serializedAst;
-        private volatile Reference<FunctionNode> cachedAst;
+        private volatile transient Reference<FunctionNode> cachedAst;
+
+        private static final long serialVersionUID = 1L;
 
         SerializedAst(final FunctionNode fn, final Reference<FunctionNode> cachedAst) {
             this.serializedAst = AstSerializer.serialize(fn);
@@ -1038,8 +1045,20 @@
         return true;
     }
 
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        final Object localCachedAst = cachedAst;
+        out.defaultWriteObject();
+        // We need to persist SerializedAst for split functions as they can't reparse the source code.
+        if (localCachedAst instanceof SerializedAst) {
+            out.writeObject(localCachedAst);
+        } else {
+            out.writeObject(null);
+        }
+    }
+
     private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
+        cachedAst = in.readObject();
         createLogger();
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/fx/base.js	Tue Jan 17 07:41:04 2017 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/fx/base.js	Wed Jul 05 22:42:01 2017 +0200
@@ -108,7 +108,7 @@
         }
     });
 
-    Files.walkFileTree(rootDirectories[0], new JRTFSWalker());
+    Files.walkFileTree(rootDirectories.toArray()[0], new JRTFSWalker());
 })();
 
 LOAD_FX_CLASSES(this, "javafx.base");
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/test/CodeStoreAndPathTest.java	Tue Jan 17 07:41:04 2017 +0100
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/CodeStoreAndPathTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -47,7 +47,7 @@
 @SuppressWarnings("javadoc")
 public class CodeStoreAndPathTest {
 
-    final String code1 = "var code1; var x = 'Hello Script'; var x1 = 'Hello Script'; "
+    final static String code1 = "var code1; var x = 'Hello Script'; var x1 = 'Hello Script'; "
                 + "var x2 = 'Hello Script'; var x3 = 'Hello Script'; "
                 + "var x4 = 'Hello Script'; var x5 = 'Hello Script';"
                 + "var x6 = 'Hello Script'; var x7 = 'Hello Script'; "
@@ -69,7 +69,7 @@
                 + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
                 + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
                 + "var x10 = 'Hello Script';}";
-    final String code2 = "var code2; var x = 'Hello Script'; var x1 = 'Hello Script'; "
+    final static String code2 = "var code2; var x = 'Hello Script'; var x1 = 'Hello Script'; "
                 + "var x2 = 'Hello Script'; var x3 = 'Hello Script'; "
                 + "var x4 = 'Hello Script'; var x5 = 'Hello Script';"
                 + "var x6 = 'Hello Script'; var x7 = 'Hello Script'; "
@@ -92,9 +92,306 @@
                 + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
                 + "var x10 = 'Hello Script';}";
     // Script size < Default minimum size for storing a compiled script class
-    final String code3 = "var code3; var x = 'Hello Script'; var x1 = 'Hello Script'; ";
-    final String codeCache = "build/nashorn_code_cache";
-    final String oldUserDir = System.getProperty("user.dir");
+    final static String code3 = "var code3; var x = 'Hello Script'; var x1 = 'Hello Script'; ";
+    final static String nestedFunctions = "\n" +
+            "(function outer() { \n" +
+            "    var map = null; \n" +
+            "    (function inner() { \n" +
+            "        var object; \n" +
+            "        if (map === null) { \n" +
+            "            map = (function() { \n" +
+            "                var HashMap = Java.type('java.util.HashMap'); \n" +
+            "                map = new HashMap(); \n" +
+            "                map.name          = 'name'; \n" +
+            "                map.id            = 1234;\n" +
+            "                map.basePath      = 'basePath'; \n" +
+            "                map.extensionPath = 'extension';\n" +
+            "                map.address       = 'address'; \n" +
+            "                map.name          = 'name'; \n" +
+            "                map.id            = 1234;\n" +
+            "                map.basePath      = 'basePath'; \n" +
+            "                map.extensionPath = 'extension';\n" +
+            "                map.address       = 'address';\n" +
+            "                map.name          = 'name'; \n" +
+            "                map.id            = 1234;\n" +
+            "                map.basePath      = 'basePath'; \n" +
+            "                map.extensionPath = 'extension';\n" +
+            "                map.address       = 'address'; \n" +
+            "                return map; \n" +
+            "            }()); \n" +
+            "        } \n" +
+            "        object = {}; \n" +
+            "        return object; \n" +
+            "    })(); \n" +
+            "}()); ";
+    final static String longNestedFunctions = "\n" +
+            "(function outer() { \n" +
+            "    var map = null; \n" +
+            "    (function inner() { \n" +
+            "        var object; \n" +
+            "        var HashMap = Java.type('java.util.HashMap'); \n" +
+            "        map = new HashMap(); \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address';\n" +
+            "        map.name          = 'name'; \n" +
+            "        map.id            = 1234;\n" +
+            "        map.basePath      = 'basePath'; \n" +
+            "        map.extensionPath = 'extension';\n" +
+            "        map.address       = 'address'; \n" +
+            "        object = {}; \n" +
+            "        return object; \n" +
+            "    })(); \n" +
+            "}()); ";
+    final static String codeCache = "build/nashorn_code_cache";
+    final static String oldUserDir = System.getProperty("user.dir");
 
     private static final String[] ENGINE_OPTIONS_OPT   = new String[]{"--persistent-code-cache", "--optimistic-types=true"};
     private static final String[] ENGINE_OPTIONS_NOOPT = new String[]{"--persistent-code-cache", "--optimistic-types=false"};
@@ -166,6 +463,28 @@
         checkCompiledScripts(stream, 4);
     }
 
+    @Test
+    public void testNestedFunctionStore() throws ScriptException, IOException {
+        System.setProperty("nashorn.persistent.code.cache", codeCache);
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(nestedFunctions);
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(nestedFunctions);
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(nestedFunctions);
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(nestedFunctions);
+    }
+
+    @Test
+    public void testSplitFunctionStore() throws ScriptException, IOException {
+        System.setProperty("nashorn.persistent.code.cache", codeCache);
+        System.setProperty("nashorn.compiler.splitter.threshold", "500");
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(longNestedFunctions);
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(longNestedFunctions);
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(longNestedFunctions);
+        factory.getScriptEngine(ENGINE_OPTIONS_OPT).eval(longNestedFunctions);
+        System.getProperties().remove("nashorn.compiler.splitter.threshold");
+    }
+
     private static Path getCodeCachePath(final boolean optimistic) {
         final String codeCache = System.getProperty("nashorn.persistent.code.cache");
         final Path codeCachePath = FileSystems.getDefault().getPath(codeCache).toAbsolutePath();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/PropertyMapTest.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.test;
+
+import java.util.Iterator;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for PropertyMap functionality
+ *
+ * @test
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime
+ * @run testng jdk.nashorn.internal.runtime.test.PropertyMapTest
+ */
+@SuppressWarnings("javadoc")
+public class PropertyMapTest {
+
+    @Test
+    public void propertyMapIteratorTest() {
+        final ScriptObject scriptObject = new ScriptObject(PropertyMap.newMap()) {};
+        Assert.assertFalse(scriptObject.getMap().iterator().hasNext());
+
+        scriptObject.set("a", "a", 0);
+        scriptObject.set("b", 3, 0);
+        // 3 is a valid array key not stored in property map
+        scriptObject.set(3, 1, 0);
+        scriptObject.set(6.5, 1.3, 0);
+        final Iterator<Object> iterator = scriptObject.getMap().iterator();
+
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), "a");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), "b");
+        Assert.assertTrue(iterator.hasNext());
+        Assert.assertEquals(iterator.next(), "6.5");
+        Assert.assertFalse(iterator.hasNext());
+    }
+
+}
--- a/test/failure_handler/src/share/conf/mac.properties	Tue Jan 17 07:41:04 2017 +0100
+++ b/test/failure_handler/src/share/conf/mac.properties	Wed Jul 05 22:42:01 2017 +0200
@@ -64,7 +64,7 @@
 native.core.app=bash
 native.core.delimiter=\0
 native.core.args=-c\0gcore -o ./core.%p %p || \
-  (DevToolsSecurity --status | grep -q enabled && lldb -o 'attach %p' -o 'process save-core core.%p' -o 'detach' -o 'quit')
+  (DevToolsSecurity --status | grep -q enabled && lldb --batch -o 'attach %p' -o 'process save-core core.%p' -o 'detach' -o 'quit')
 native.core.params.timeout=3600000
 ################################################################################
 # environment info to gather
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/SecurityTools.java	Wed Jul 05 22:42:01 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class SecurityTools {
+
+    public static final String NO_ALIAS = null;
+
+    // keytool
+
+    public static OutputAnalyzer keytool(List<String> options)
+            throws Throwable {
+
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("keytool")
+                .addVMArg("-Duser.language=en")
+                .addVMArg("-Duser.country=US");
+        for (String option : options) {
+            if (option.startsWith("-J")) {
+                launcher.addVMArg(option.substring(2));
+            } else {
+                launcher.addToolArg(option);
+            }
+        }
+        return ProcessTools.executeCommand(launcher.getCommand());
+    }
+
+    public static OutputAnalyzer keytool(String options) throws Throwable {
+        return keytool(options.split("\\s+"));
+    }
+
+    public static OutputAnalyzer keytool(String... options) throws Throwable {
+        return keytool(List.of(options));
+    }
+
+    // jarsigner
+
+    public static OutputAnalyzer jarsigner(String jar, String alias,
+            List<String> options) throws Throwable {
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
+                .addVMArg("-Duser.language=en")
+                .addVMArg("-Duser.country=US");
+        for (String option : options) {
+            if (option.startsWith("-J")) {
+                launcher.addVMArg(option.substring(2));
+            } else {
+                launcher.addToolArg(option);
+            }
+        }
+        launcher.addToolArg(jar);
+        if (alias != null) {
+            launcher.addToolArg(alias);
+        }
+        return ProcessTools.executeCommand(launcher.getCommand());
+    }
+
+    public static OutputAnalyzer jarsigner(String jar, String alias,
+            String options) throws Throwable {
+
+        return jarsigner(jar, alias, options.split("\\s+"));
+    }
+
+    public static OutputAnalyzer jarsigner(String jar, String alias,
+            String... options) throws Throwable {
+
+        return jarsigner(jar, alias, List.of(options));
+    }
+
+    public static OutputAnalyzer sign(String jar, String alias, String... options)
+            throws Throwable {
+
+        return jarsigner(jar, alias,
+                mergeOptions("-J-Djava.security.egd=file:/dev/./urandom", options));
+    }
+
+    public static OutputAnalyzer verify(String jar, String... options)
+            throws Throwable {
+
+        return jarsigner(jar, NO_ALIAS, mergeOptions("-verify", options));
+    }
+
+    // helper methods
+
+    private static List<String> mergeOptions(
+            String firstOption, String... secondPart) {
+
+        return mergeOptions(List.of(firstOption), secondPart);
+    }
+
+    private static List<String> mergeOptions(
+            List<String> firstPart, String... secondPart) {
+
+        List<String> options = new ArrayList<>(firstPart);
+        Collections.addAll(options, secondPart);
+        return options;
+    }
+}
+