Merge
diff --git a/.hgignore b/.hgignore
index 9aab81c..023de87 100644
--- a/.hgignore
+++ b/.hgignore
@@ -3,8 +3,7 @@
 ^.idea/
 nbproject/private/
 ^webrev
-^.hgtip
-^.bridge2
+^.src-rev$
 ^.jib/
 .DS_Store
 .metadata/
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 58e9fe7..a1da575 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -389,3 +389,4 @@
 8d337fd6333e28c48aa87880144b840aad82baaf jdk-9+144
 ff98aa9ec9fae991e426ce5926fc9036d25f5562 jdk-9+145
 a22e2671d88f6b22a4aa82e3966986542ed2a381 jdk-9+146
+5f6920274c48eb00d31afee6c034826a754c13d9 jdk-9+147
diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4
index ab2bd9a..f75f3ad 100644
--- a/common/autoconf/boot-jdk.m4
+++ b/common/autoconf/boot-jdk.m4
@@ -98,7 +98,7 @@
   fi
 ])
 
-# Test: Is bootjdk explicitely set by command line arguments?
+# Test: Is bootjdk explicitly set by command line arguments?
 AC_DEFUN([BOOTJDK_CHECK_ARGUMENTS],
 [
   if test "x$with_boot_jdk" != x; then
@@ -238,7 +238,7 @@
       $1=$BOOT_JDK/bin/$2
       if test ! -x [$]$1; then
         AC_MSG_RESULT(not found)
-        AC_MSG_NOTICE([Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk])
+        AC_MSG_NOTICE([Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk])
         AC_MSG_ERROR([Could not find $2 in the Boot JDK])
       fi
       AC_MSG_RESULT(ok)
@@ -262,7 +262,7 @@
   # we detected something (if so, the path to the jdk is in BOOT_JDK). But we
   # must check if this is indeed valid; otherwise we'll continue looking.
 
-  # Test: Is bootjdk explicitely set by command line arguments?
+  # Test: Is bootjdk explicitly set by command line arguments?
   BOOTJDK_DO_CHECK([BOOTJDK_CHECK_ARGUMENTS])
   if test "x$with_boot_jdk" != x && test "x$BOOT_JDK_FOUND" = xno; then
     # Having specified an argument which is incorrect will produce an instant failure;
@@ -286,7 +286,7 @@
   if test "x$BOOT_JDK_FOUND" = xno; then
     HELP_MSG_MISSING_DEPENDENCY([openjdk])
     AC_MSG_NOTICE([Could not find a valid Boot JDK. $HELP_MSG])
-    AC_MSG_NOTICE([This might be fixed by explicitely setting --with-boot-jdk])
+    AC_MSG_NOTICE([This might be fixed by explicitly setting --with-boot-jdk])
     AC_MSG_ERROR([Cannot continue])
   fi
 
diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4
index 8638750..fd77fe8 100644
--- a/common/autoconf/build-performance.m4
+++ b/common/autoconf/build-performance.m4
@@ -217,6 +217,13 @@
 AC_DEFUN([BPERF_SETUP_CCACHE_USAGE],
 [
   if test "x$CCACHE" != x; then
+    if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
+      HAS_BAD_CCACHE=[`$ECHO $CCACHE_VERSION | \
+          $GREP -e '^1\.' -e '^2\.' -e '^3\.0\.' -e '^3\.1\.'`]
+      if test "x$HAS_BAD_CCACHE" != "x"; then
+        AC_MSG_ERROR([On macosx, ccache 3.2 or later is required, found $CCACHE_VERSION])
+      fi
+    fi
     if test "x$USE_PRECOMPILED_HEADER" = "x1"; then
       HAS_BAD_CCACHE=[`$ECHO $CCACHE_VERSION | \
           $GREP -e '^1.*' -e '^2.*' -e '^3\.0.*' -e '^3\.1\.[0123]$'`]
diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in
index dba0760..ddd388c 100644
--- a/common/autoconf/buildjdk-spec.gmk.in
+++ b/common/autoconf/buildjdk-spec.gmk.in
@@ -86,73 +86,13 @@
 # Save speed and disk space by not enabling debug symbols for the buildjdk
 ENABLE_DEBUG_SYMBOLS := false
 
-####################################################
-#
-# Legacy Hotspot support
+# Control wether Hotspot builds gtest tests
+BUILD_GTEST := false
 
-# Legacy setting: OPT or DBG
-VARIANT := OPT
-# Legacy setting: true or false
-FASTDEBUG := false
-# Legacy setting: debugging the class files?
-DEBUG_CLASSFILES := false
+JVM_VARIANTS := server
 
 # Some users still set EXTRA_*FLAGS on the make command line. Must
 # make sure to override that when building buildjdk.
 override EXTRA_CFLAGS :=
 override EXTRA_CXXFLAGS :=
 override EXTRA_LDFLAGS :=
-
-# The HOSTCC/HOSTCXX is Hotspot terminology for the BUILD_CC/BUILD_CXX, i.e. the
-# compiler that produces code that can be run on the build platform.
-HOSTCC := $(BUILD_CC)
-HOSTCXX := $(BUILD_CXX)
-
-# Old name for OPENJDK_TARGET_OS (aix,bsd,hpux,linux,macosx,solaris,windows etc)
-PLATFORM := $(OPENJDK_BUILD_OS)
-# 32 or 64 bit
-ARCH_DATA_MODEL := $(OPENJDK_BUILD_CPU_BITS)
-
-ALT_BOOTDIR := $(BOOT_JDK)
-# Yet another name for arch used for an extra subdir below the jvm lib.
-# Uses i386 and amd64, instead of x86 and x86_64.
-LIBARCH := @OPENJDK_BUILD_CPU_LEGACY_LIB@
-# Set the cpu architecture. Some users still set ARCH on the make command line. Must
-# make sure to override that when building buildjdk.
-override ARCH := $(OPENJDK_BUILD_CPU_ARCH)
-# Legacy setting for building for a 64 bit machine.
-# If yes then this expands to _LP64 := 1
-ifeq ($(OPENJDK_BUILD_CPU_BITS), 64)
-  _LP64 := 1
-endif
-
-ALT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)
-ALT_EXPORT_PATH := $(HOTSPOT_DIST)
-
-JVM_INTERPRETER := @JVM_INTERPRETER@
-ifeq ($(JVM_INTERPRETER), cpp)
-  CC_INTERP=true
-endif
-
-HOTSPOT_MAKE_ARGS := product docs export_product
-
-# Control wether Hotspot builds gtest tests
-BUILD_GTEST := false
-
-USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@
-
-# Hotspot expects the variable FULL_DEBUG_SYMBOLS=1/0 to control debug symbols
-# creation.
-FULL_DEBUG_SYMBOLS := 0
-ZIP_DEBUGINFO_FILES := 0
-# Disable stripping
-STRIP_POLICY := none
-
-JVM_VARIANTS := server
-JVM_VARIANT_SERVER := true
-JVM_VARIANT_CLIENT := false
-JVM_VARIANT_MINIMAL1 := false
-JVM_VARIANT_KERNEL := false
-JVM_VARIANT_ZERO := false
-JVM_VARIANT_ZEROSHARK := false
-JVM_VARIANT_CORE := false
diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac
index bb5491b..4879d05 100644
--- a/common/autoconf/configure.ac
+++ b/common/autoconf/configure.ac
@@ -182,7 +182,6 @@
 
 # Finally do some processing after the detection phase
 TOOLCHAIN_SETUP_BUILD_COMPILERS
-TOOLCHAIN_SETUP_LEGACY
 TOOLCHAIN_MISC_CHECKS
 
 # Setup the JTReg Regression Test Harness.
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index ba1e8db..767f6be 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -1378,7 +1378,7 @@
 
   AC_MSG_CHECKING([if native warnings are errors])
   if test "x$enable_warnings_as_errors" = "xyes"; then
-    AC_MSG_RESULT([yes (explicitely set)])
+    AC_MSG_RESULT([yes (explicitly set)])
     WARNINGS_AS_ERRORS=true
   elif test "x$enable_warnings_as_errors" = "xno"; then
     AC_MSG_RESULT([no])
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 9179032..8a665cb 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -700,8 +700,6 @@
 JVM_FEATURES_server
 INCLUDE_DTRACE
 GCOV_ENABLED
-STRIP_POLICY
-DEBUG_BINARIES
 ZIP_EXTERNAL_DEBUG_SYMBOLS
 COPY_DEBUG_SYMBOLS
 COMPILE_WITH_DEBUG_SYMBOLS
@@ -791,11 +789,6 @@
 HOTSPOT_TOOLCHAIN_TYPE
 USING_BROKEN_SUSE_LD
 PACKAGE_PATH
-USE_CLANG
-HOTSPOT_LD
-HOTSPOT_CXX
-HOTSPOT_RC
-HOTSPOT_MT
 BUILD_AS
 BUILD_LDCXX
 BUILD_LD
@@ -1974,8 +1967,8 @@
   --enable-debug          set the debug level to fastdebug (shorthand for
                           --with-debug-level=fastdebug) [disabled]
   --enable-headless-only  only build headless (no GUI) support [disabled]
-  --enable-unlimited-crypto
-                          Enable unlimited crypto policy [disabled]
+  --disable-unlimited-crypto
+                          Disable unlimited crypto policy [enabled]
   --disable-keep-packaged-modules
                           Do not keep packaged modules in jdk image [enable]
   --enable-static-build   enable static library build [disabled]
@@ -3851,7 +3844,7 @@
 # $1 A command line (typically autoconf macro) to execute
 
 
-# Test: Is bootjdk explicitely set by command line arguments?
+# Test: Is bootjdk explicitly set by command line arguments?
 
 
 # Test: Is $JAVA_HOME set?
@@ -4911,7 +4904,7 @@
 # Minimum supported versions, empty means unspecified
 TOOLCHAIN_MINIMUM_VERSION_clang="3.2"
 TOOLCHAIN_MINIMUM_VERSION_gcc="4.3"
-TOOLCHAIN_MINIMUM_VERSION_microsoft=""
+TOOLCHAIN_MINIMUM_VERSION_microsoft="16.00.30319.01" # VS2010
 TOOLCHAIN_MINIMUM_VERSION_solstudio="5.13"
 TOOLCHAIN_MINIMUM_VERSION_xlc=""
 
@@ -4982,10 +4975,6 @@
 # for this, we can only do this after these have been setup.
 
 
-# Setup legacy variables that are still needed as alternative ways to refer to
-# parts of the toolchain.
-
-
 # Do some additional checks on the detected tools.
 
 
@@ -5093,7 +5082,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1479997904
+DATE_WHEN_GENERATED=1480714260
 
 ###############################################################################
 #
@@ -15523,7 +15512,7 @@
       ;;
   esac
 
-  # ..and setup our own variables. (Do this explicitely to facilitate searching)
+  # ..and setup our own variables. (Do this explicitly to facilitate searching)
   OPENJDK_BUILD_OS="$VAR_OS"
   if test "x$VAR_OS_TYPE" != x; then
     OPENJDK_BUILD_OS_TYPE="$VAR_OS_TYPE"
@@ -15662,7 +15651,7 @@
       ;;
   esac
 
-  # ... and setup our own variables. (Do this explicitely to facilitate searching)
+  # ... and setup our own variables. (Do this explicitly to facilitate searching)
   OPENJDK_TARGET_OS="$VAR_OS"
   if test "x$VAR_OS_TYPE" != x; then
     OPENJDK_TARGET_OS_TYPE="$VAR_OS_TYPE"
@@ -24240,7 +24229,7 @@
 if test "${enable_unlimited_crypto+set}" = set; then :
   enableval=$enable_unlimited_crypto;
 else
-  enable_unlimited_crypto=no
+  enable_unlimited_crypto=yes
 fi
 
   if test "x$enable_unlimited_crypto" = "xyes"; then
@@ -24400,7 +24389,7 @@
         as_fn_error $? "Version string contains + but both 'BUILD' and 'OPT' are missing" "$LINENO" 5
       fi
       # Stop the version part process from setting default values.
-      # We still allow them to explicitely override though.
+      # We still allow them to explicitly override though.
       NO_DEFAULT_VERSION_PARTS=true
     else
       as_fn_error $? "--with-version-string fails to parse as a valid version string: $with_version_string" "$LINENO" 5
@@ -24769,7 +24758,7 @@
   # we detected something (if so, the path to the jdk is in BOOT_JDK). But we
   # must check if this is indeed valid; otherwise we'll continue looking.
 
-  # Test: Is bootjdk explicitely set by command line arguments?
+  # Test: Is bootjdk explicitly set by command line arguments?
 
   if test "x$BOOT_JDK_FOUND" = xno; then
     # Now execute the test
@@ -29887,8 +29876,8 @@
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find a valid Boot JDK. $HELP_MSG" >&5
 $as_echo "$as_me: Could not find a valid Boot JDK. $HELP_MSG" >&6;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: This might be fixed by explicitly setting --with-boot-jdk" >&6;}
     as_fn_error $? "Cannot continue" "$LINENO" 5
   fi
 
@@ -29910,8 +29899,8 @@
       if test ! -x $JAVA; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find java in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -29938,8 +29927,8 @@
       if test ! -x $JAVA; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find java in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30048,8 +30037,8 @@
       if test ! -x $JAVAC; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find javac in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30076,8 +30065,8 @@
       if test ! -x $JAVAC; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find javac in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30186,8 +30175,8 @@
       if test ! -x $JAVAH; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find javah in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30214,8 +30203,8 @@
       if test ! -x $JAVAH; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find javah in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30324,8 +30313,8 @@
       if test ! -x $JAR; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find jar in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30352,8 +30341,8 @@
       if test ! -x $JAR; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find jar in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30462,8 +30451,8 @@
       if test ! -x $JARSIGNER; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find jarsigner in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -30490,8 +30479,8 @@
       if test ! -x $JARSIGNER; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
 $as_echo "not found" >&6; }
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&5
-$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitely setting --with-boot-jdk" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&5
+$as_echo "$as_me: Your Boot JDK seems broken. This might be fixed by explicitly setting --with-boot-jdk" >&6;}
         as_fn_error $? "Could not find jarsigner in the Boot JDK" "$LINENO" 5
       fi
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
@@ -31198,6 +31187,12 @@
   if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
     IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
   fi
+  # Workaround for using different imported module-info.java in Jake due to a
+  # change in format. Remove once new format is standard in JDK 9 and javafx
+  # delivers just that.
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_src_jake"; then
+    IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src_jake $IMPORT_MODULES_SRC"
+  fi
   if test -d "$IMPORT_MODULES_TOPDIR/make"; then
     IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
   fi
@@ -33578,9 +33573,11 @@
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
     # cc -V output typically looks like
     #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    # or
+    #     cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2016/05/31
     COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
     # Check that this is likely to be the Solaris Studio cc.
-    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.* Sun $COMPILER_NAME" > /dev/null
     if test $? -ne 0; then
       ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
       { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
@@ -34875,9 +34872,11 @@
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
     # cc -V output typically looks like
     #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    # or
+    #     cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2016/05/31
     COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
     # Check that this is likely to be the Solaris Studio cc.
-    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.* Sun $COMPILER_NAME" > /dev/null
     if test $? -ne 0; then
       ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
       { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
@@ -35261,9 +35260,9 @@
   fi
 
   # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
-  if  [[ "[$]CC_VERSION_NUMBER" =~ (.*\.){3} ]] ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&5
-$as_echo "$as_me: WARNING: C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
+  if  [[ "[$]CC_VERSION_NUMBER" =~ (.*\.){4} ]] ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than four parts (W.X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&5
+$as_echo "$as_me: WARNING: C compiler version number has more than four parts (W.X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
   if  [[  "[$]CC_VERSION_NUMBER" =~ [0-9]{6} ]] ; then
@@ -35271,7 +35270,7 @@
 $as_echo "$as_me: WARNING: C compiler version number has a part larger than 99999: $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
-  COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$CC_VERSION_NUMBER"`
+  COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$CC_VERSION_NUMBER"`
 
 
   if test "x$TOOLCHAIN_MINIMUM_VERSION" != x; then
@@ -35329,8 +35328,8 @@
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=$TOOLCHAIN_MINIMUM_VERSION
 
-  if  [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then
-    as_fn_error $? "Internal error: Cannot compare to $TOOLCHAIN_MINIMUM_VERSION, only three parts (X.Y.Z) is supported" "$LINENO" 5
+  if  [[ "$REFERENCE_VERSION" =~ (.*\.){4} ]] ; then
+    as_fn_error $? "Internal error: Cannot compare to $TOOLCHAIN_MINIMUM_VERSION, only four parts (W.X.Y.Z) is supported" "$LINENO" 5
   fi
 
   if  [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then
@@ -35338,7 +35337,7 @@
   fi
 
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
-  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
+  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$REFERENCE_VERSION"`
 
   if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
@@ -46956,9 +46955,11 @@
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
     # cc -V output typically looks like
     #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    # or
+    #     cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2016/05/31
     COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
     # Check that this is likely to be the Solaris Studio cc.
-    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.* Sun $COMPILER_NAME" > /dev/null
     if test $? -ne 0; then
       ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
       { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
@@ -47076,9 +47077,11 @@
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
     # cc -V output typically looks like
     #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    # or
+    #     cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2016/05/31
     COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
     # Check that this is likely to be the Solaris Studio cc.
-    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.* Sun $COMPILER_NAME" > /dev/null
     if test $? -ne 0; then
       ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
       { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
@@ -47198,9 +47201,9 @@
   fi
 
   # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
-  if  [[ "[$]BUILD_CC_VERSION_NUMBER" =~ (.*\.){3} ]] ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than three parts (X.Y.Z): $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&5
-$as_echo "$as_me: WARNING: C compiler version number has more than three parts (X.Y.Z): $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
+  if  [[ "[$]BUILD_CC_VERSION_NUMBER" =~ (.*\.){4} ]] ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than four parts (W.X.Y.Z): $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&5
+$as_echo "$as_me: WARNING: C compiler version number has more than four parts (W.X.Y.Z): $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
   if  [[  "[$]BUILD_CC_VERSION_NUMBER" =~ [0-9]{6} ]] ; then
@@ -47208,7 +47211,7 @@
 $as_echo "$as_me: WARNING: C compiler version number has a part larger than 99999: $BUILD_CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
-  OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$BUILD_CC_VERSION_NUMBER"`
+  OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$BUILD_CC_VERSION_NUMBER"`
 
   else
     # If we are not cross compiling, use the normal target compilers for
@@ -47234,9 +47237,9 @@
   fi
 
   # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
-  if  [[ "[$]CC_VERSION_NUMBER" =~ (.*\.){3} ]] ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&5
-$as_echo "$as_me: WARNING: C compiler version number has more than three parts (X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
+  if  [[ "[$]CC_VERSION_NUMBER" =~ (.*\.){4} ]] ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C compiler version number has more than four parts (W.X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&5
+$as_echo "$as_me: WARNING: C compiler version number has more than four parts (W.X.Y.Z): $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
   if  [[  "[$]CC_VERSION_NUMBER" =~ [0-9]{6} ]] ; then
@@ -47244,7 +47247,7 @@
 $as_echo "$as_me: WARNING: C compiler version number has a part larger than 99999: $CC_VERSION_NUMBER. Comparisons might be wrong." >&2;}
   fi
 
-  OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$CC_VERSION_NUMBER"`
+  OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$CC_VERSION_NUMBER"`
 
   fi
 
@@ -47259,68 +47262,6 @@
 
 
 
-  if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
-    # For hotspot, we need these in Windows mixed path,
-    # so rewrite them all. Need added .exe suffix.
-    HOTSPOT_CXX="$CXX.exe"
-    HOTSPOT_LD="$LD.exe"
-    HOTSPOT_MT="$MT.exe"
-    HOTSPOT_RC="$RC.exe"
-
-  unix_path="$HOTSPOT_CXX"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    windows_path=`$CYGPATH -m "$unix_path"`
-    HOTSPOT_CXX="$windows_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    windows_path=`cmd //c echo $unix_path`
-    HOTSPOT_CXX="$windows_path"
-  fi
-
-
-  unix_path="$HOTSPOT_LD"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    windows_path=`$CYGPATH -m "$unix_path"`
-    HOTSPOT_LD="$windows_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    windows_path=`cmd //c echo $unix_path`
-    HOTSPOT_LD="$windows_path"
-  fi
-
-
-  unix_path="$HOTSPOT_MT"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    windows_path=`$CYGPATH -m "$unix_path"`
-    HOTSPOT_MT="$windows_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    windows_path=`cmd //c echo $unix_path`
-    HOTSPOT_MT="$windows_path"
-  fi
-
-
-  unix_path="$HOTSPOT_RC"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    windows_path=`$CYGPATH -m "$unix_path"`
-    HOTSPOT_RC="$windows_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    windows_path=`cmd //c echo $unix_path`
-    HOTSPOT_RC="$windows_path"
-  fi
-
-
-
-  else
-    HOTSPOT_CXX="$CXX"
-    HOTSPOT_LD="$LD"
-  fi
-
-
-
-  if test  "x$TOOLCHAIN_TYPE" = xclang; then
-    USE_CLANG=true
-  fi
-
-
-
 
 
   # The package path is used only on macosx?
@@ -49914,8 +49855,8 @@
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=6
 
-  if  [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then
-    as_fn_error $? "Internal error: Cannot compare to 6, only three parts (X.Y.Z) is supported" "$LINENO" 5
+  if  [[ "$REFERENCE_VERSION" =~ (.*\.){4} ]] ; then
+    as_fn_error $? "Internal error: Cannot compare to 6, only four parts (W.X.Y.Z) is supported" "$LINENO" 5
   fi
 
   if  [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then
@@ -49923,7 +49864,7 @@
   fi
 
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
-  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
+  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$REFERENCE_VERSION"`
 
   if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
@@ -50214,8 +50155,8 @@
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=4.8
 
-  if  [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then
-    as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5
+  if  [[ "$REFERENCE_VERSION" =~ (.*\.){4} ]] ; then
+    as_fn_error $? "Internal error: Cannot compare to 4.8, only four parts (W.X.Y.Z) is supported" "$LINENO" 5
   fi
 
   if  [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then
@@ -50223,7 +50164,7 @@
   fi
 
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
-  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
+  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$REFERENCE_VERSION"`
 
   if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
@@ -50737,8 +50678,8 @@
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=6
 
-  if  [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then
-    as_fn_error $? "Internal error: Cannot compare to 6, only three parts (X.Y.Z) is supported" "$LINENO" 5
+  if  [[ "$REFERENCE_VERSION" =~ (.*\.){4} ]] ; then
+    as_fn_error $? "Internal error: Cannot compare to 6, only four parts (W.X.Y.Z) is supported" "$LINENO" 5
   fi
 
   if  [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then
@@ -50746,7 +50687,7 @@
   fi
 
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
-  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
+  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$REFERENCE_VERSION"`
 
   if test $OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
@@ -51037,8 +50978,8 @@
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=4.8
 
-  if  [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then
-    as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5
+  if  [[ "$REFERENCE_VERSION" =~ (.*\.){4} ]] ; then
+    as_fn_error $? "Internal error: Cannot compare to 4.8, only four parts (W.X.Y.Z) is supported" "$LINENO" 5
   fi
 
   if  [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then
@@ -51046,7 +50987,7 @@
   fi
 
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
-  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"`
+  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", $1, $2, $3, $4) }' <<< "$REFERENCE_VERSION"`
 
   if test $OPENJDK_BUILD_COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
@@ -51917,8 +51858,8 @@
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking if native warnings are errors" >&5
 $as_echo_n "checking if native warnings are errors... " >&6; }
   if test "x$enable_warnings_as_errors" = "xyes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (explicitely set)" >&5
-$as_echo "yes (explicitely set)" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (explicitly set)" >&5
+$as_echo "yes (explicitly set)" >&6; }
     WARNINGS_AS_ERRORS=true
   elif test "x$enable_warnings_as_errors" = "xno"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
@@ -52583,28 +52524,14 @@
     COMPILE_WITH_DEBUG_SYMBOLS=true
     COPY_DEBUG_SYMBOLS=true
     ZIP_EXTERNAL_DEBUG_SYMBOLS=true
-
-    # Hotspot legacy support, not relevant with COPY_DEBUG_SYMBOLS=true
-    DEBUG_BINARIES=false
-    STRIP_POLICY=min_strip
-
   elif test "x$NATIVE_DEBUG_SYMBOLS" = xnone; then
     COMPILE_WITH_DEBUG_SYMBOLS=false
     COPY_DEBUG_SYMBOLS=false
     ZIP_EXTERNAL_DEBUG_SYMBOLS=false
-
-    DEBUG_BINARIES=false
-    STRIP_POLICY=no_strip
   elif test "x$NATIVE_DEBUG_SYMBOLS" = xinternal; then
     COMPILE_WITH_DEBUG_SYMBOLS=true
     COPY_DEBUG_SYMBOLS=false
     ZIP_EXTERNAL_DEBUG_SYMBOLS=false
-
-    # Hotspot legacy support, will turn on -g when COPY_DEBUG_SYMBOLS=false
-    DEBUG_BINARIES=true
-    STRIP_POLICY=no_strip
-    STRIP=""
-
   elif test "x$NATIVE_DEBUG_SYMBOLS" = xexternal; then
 
     if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
@@ -52618,10 +52545,6 @@
     COMPILE_WITH_DEBUG_SYMBOLS=true
     COPY_DEBUG_SYMBOLS=true
     ZIP_EXTERNAL_DEBUG_SYMBOLS=false
-
-    # Hotspot legacy support, not relevant with COPY_DEBUG_SYMBOLS=true
-    DEBUG_BINARIES=false
-    STRIP_POLICY=min_strip
   else
     as_fn_error $? "Allowed native debug symbols are: none, internal, external, zipped" "$LINENO" 5
   fi
@@ -52670,10 +52593,6 @@
 
 
 
-  # Legacy values
-
-
-
 
   # Check whether --enable-native-coverage was given.
 if test "${enable_native_coverage+set}" = set; then :
@@ -53195,7 +53114,7 @@
 
 
   if test "x$with_msvcr_dll" != x; then
-    # If given explicitely by user, do not probe. If not present, fail directly.
+    # If given explicitly by user, do not probe. If not present, fail directly.
 
   DLL_NAME="$MSVCR_NAME"
   POSSIBLE_MSVC_DLL="$with_msvcr_dll"
@@ -54544,7 +54463,7 @@
 
   if test "x$MSVCP_NAME" != "x"; then
     if test "x$with_msvcp_dll" != x; then
-      # If given explicitely by user, do not probe. If not present, fail directly.
+      # If given explicitly by user, do not probe. If not present, fail directly.
 
   DLL_NAME="$MSVCP_NAME"
   POSSIBLE_MSVC_DLL="$with_msvcp_dll"
@@ -55903,7 +55822,7 @@
 
     if test "x${with_x}" != x &&  test "x${with_x}" != xyes; then
       # The user has specified a X11 base directory. Use it for includes and
-      # libraries, unless explicitely overridden.
+      # libraries, unless explicitly overridden.
       if test "x$x_includes" = xNONE; then
         x_includes="${with_x}/include"
       fi
@@ -65525,6 +65444,13 @@
   if test "x$CCACHE" != x; then
 
   if test "x$CCACHE" != x; then
+    if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
+      HAS_BAD_CCACHE=`$ECHO $CCACHE_VERSION | \
+          $GREP -e '^1\.' -e '^2\.' -e '^3\.0\.' -e '^3\.1\.'`
+      if test "x$HAS_BAD_CCACHE" != "x"; then
+        as_fn_error $? "On macosx, ccache 3.2 or later is required, found $CCACHE_VERSION" "$LINENO" 5
+      fi
+    fi
     if test "x$USE_PRECOMPILED_HEADER" = "x1"; then
       HAS_BAD_CCACHE=`$ECHO $CCACHE_VERSION | \
           $GREP -e '^1.*' -e '^2.*' -e '^3\.0.*' -e '^3\.1\.[0123]$'`
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index 8becdf3..acc0dcc 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -163,9 +163,9 @@
   AC_SUBST(CACERTS_FILE)
 
   # Enable or disable unlimited crypto
-  AC_ARG_ENABLE(unlimited-crypto, [AS_HELP_STRING([--enable-unlimited-crypto],
-      [Enable unlimited crypto policy @<:@disabled@:>@])],,
-      [enable_unlimited_crypto=no])
+  AC_ARG_ENABLE(unlimited-crypto, [AS_HELP_STRING([--disable-unlimited-crypto],
+      [Disable unlimited crypto policy @<:@enabled@:>@])],,
+      [enable_unlimited_crypto=yes])
   if test "x$enable_unlimited_crypto" = "xyes"; then
     UNLIMITED_CRYPTO=true
   else
@@ -265,28 +265,14 @@
     COMPILE_WITH_DEBUG_SYMBOLS=true
     COPY_DEBUG_SYMBOLS=true
     ZIP_EXTERNAL_DEBUG_SYMBOLS=true
-
-    # Hotspot legacy support, not relevant with COPY_DEBUG_SYMBOLS=true
-    DEBUG_BINARIES=false
-    STRIP_POLICY=min_strip
-
   elif test "x$NATIVE_DEBUG_SYMBOLS" = xnone; then
     COMPILE_WITH_DEBUG_SYMBOLS=false
     COPY_DEBUG_SYMBOLS=false
     ZIP_EXTERNAL_DEBUG_SYMBOLS=false
-
-    DEBUG_BINARIES=false
-    STRIP_POLICY=no_strip
   elif test "x$NATIVE_DEBUG_SYMBOLS" = xinternal; then
     COMPILE_WITH_DEBUG_SYMBOLS=true
     COPY_DEBUG_SYMBOLS=false
     ZIP_EXTERNAL_DEBUG_SYMBOLS=false
-
-    # Hotspot legacy support, will turn on -g when COPY_DEBUG_SYMBOLS=false
-    DEBUG_BINARIES=true
-    STRIP_POLICY=no_strip
-    STRIP=""
-
   elif test "x$NATIVE_DEBUG_SYMBOLS" = xexternal; then
 
     if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
@@ -300,10 +286,6 @@
     COMPILE_WITH_DEBUG_SYMBOLS=true
     COPY_DEBUG_SYMBOLS=true
     ZIP_EXTERNAL_DEBUG_SYMBOLS=false
-
-    # Hotspot legacy support, not relevant with COPY_DEBUG_SYMBOLS=true
-    DEBUG_BINARIES=false
-    STRIP_POLICY=min_strip
   else
     AC_MSG_ERROR([Allowed native debug symbols are: none, internal, external, zipped])
   fi
@@ -321,10 +303,6 @@
   AC_SUBST(COMPILE_WITH_DEBUG_SYMBOLS)
   AC_SUBST(COPY_DEBUG_SYMBOLS)
   AC_SUBST(ZIP_EXTERNAL_DEBUG_SYMBOLS)
-
-  # Legacy values
-  AC_SUBST(DEBUG_BINARIES)
-  AC_SUBST(STRIP_POLICY)
 ])
 
 ################################################################################
diff --git a/common/autoconf/jdk-version.m4 b/common/autoconf/jdk-version.m4
index 4846c12..65df55e 100644
--- a/common/autoconf/jdk-version.m4
+++ b/common/autoconf/jdk-version.m4
@@ -110,7 +110,7 @@
         AC_MSG_ERROR([Version string contains + but both 'BUILD' and 'OPT' are missing])
       fi
       # Stop the version part process from setting default values.
-      # We still allow them to explicitely override though.
+      # We still allow them to explicitly override though.
       NO_DEFAULT_VERSION_PARTS=true
     else
       AC_MSG_ERROR([--with-version-string fails to parse as a valid version string: $with_version_string])
diff --git a/common/autoconf/lib-x11.m4 b/common/autoconf/lib-x11.m4
index 0614299..d4b878d 100644
--- a/common/autoconf/lib-x11.m4
+++ b/common/autoconf/lib-x11.m4
@@ -42,7 +42,7 @@
 
     if test "x${with_x}" != x &&  test "x${with_x}" != xyes; then
       # The user has specified a X11 base directory. Use it for includes and
-      # libraries, unless explicitely overridden.
+      # libraries, unless explicitly overridden.
       if test "x$x_includes" = xNONE; then
         x_includes="${with_x}/include"
       fi
diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4
index e7ffe4a..392a23a 100644
--- a/common/autoconf/platform.m4
+++ b/common/autoconf/platform.m4
@@ -162,7 +162,7 @@
   # Convert the autoconf OS/CPU value to our own data, into the VAR_OS/CPU variables.
   PLATFORM_EXTRACT_VARS_FROM_OS($build_os)
   PLATFORM_EXTRACT_VARS_FROM_CPU($build_cpu)
-  # ..and setup our own variables. (Do this explicitely to facilitate searching)
+  # ..and setup our own variables. (Do this explicitly to facilitate searching)
   OPENJDK_BUILD_OS="$VAR_OS"
   if test "x$VAR_OS_TYPE" != x; then
     OPENJDK_BUILD_OS_TYPE="$VAR_OS_TYPE"
@@ -192,7 +192,7 @@
   # Convert the autoconf OS/CPU value to our own data, into the VAR_OS/CPU variables.
   PLATFORM_EXTRACT_VARS_FROM_OS($host_os)
   PLATFORM_EXTRACT_VARS_FROM_CPU($host_cpu)
-  # ... and setup our own variables. (Do this explicitely to facilitate searching)
+  # ... and setup our own variables. (Do this explicitly to facilitate searching)
   OPENJDK_TARGET_OS="$VAR_OS"
   if test "x$VAR_OS_TYPE" != x; then
     OPENJDK_TARGET_OS_TYPE="$VAR_OS_TYPE"
diff --git a/common/autoconf/source-dirs.m4 b/common/autoconf/source-dirs.m4
index 940707e..81137cf 100644
--- a/common/autoconf/source-dirs.m4
+++ b/common/autoconf/source-dirs.m4
@@ -126,6 +126,12 @@
   if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
     IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
   fi
+  # Workaround for using different imported module-info.java in Jake due to a
+  # change in format. Remove once new format is standard in JDK 9 and javafx
+  # delivers just that.
+  if test -d "$IMPORT_MODULES_TOPDIR/modules_src_jake"; then
+    IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src_jake $IMPORT_MODULES_SRC"
+  fi
   if test -d "$IMPORT_MODULES_TOPDIR/make"; then
     IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
   fi
diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4
index db3d39e..16b0df0 100644
--- a/common/autoconf/toolchain.m4
+++ b/common/autoconf/toolchain.m4
@@ -53,7 +53,7 @@
 # Minimum supported versions, empty means unspecified
 TOOLCHAIN_MINIMUM_VERSION_clang="3.2"
 TOOLCHAIN_MINIMUM_VERSION_gcc="4.3"
-TOOLCHAIN_MINIMUM_VERSION_microsoft=""
+TOOLCHAIN_MINIMUM_VERSION_microsoft="16.00.30319.01" # VS2010
 TOOLCHAIN_MINIMUM_VERSION_solstudio="5.13"
 TOOLCHAIN_MINIMUM_VERSION_xlc=""
 
@@ -69,15 +69,15 @@
   fi
 
   # We only check CC_VERSION_NUMBER since we assume CXX_VERSION_NUMBER is equal.
-  if [ [[ "[$]$1CC_VERSION_NUMBER" =~ (.*\.){3} ]] ]; then
-    AC_MSG_WARN([C compiler version number has more than three parts (X.Y.Z): [$]$1CC_VERSION_NUMBER. Comparisons might be wrong.])
+  if [ [[ "[$]$1CC_VERSION_NUMBER" =~ (.*\.){4} ]] ]; then
+    AC_MSG_WARN([C compiler version number has more than four parts (W.X.Y.Z): [$]$1CC_VERSION_NUMBER. Comparisons might be wrong.])
   fi
 
   if [ [[  "[$]$1CC_VERSION_NUMBER" =~ [0-9]{6} ]] ]; then
     AC_MSG_WARN([C compiler version number has a part larger than 99999: [$]$1CC_VERSION_NUMBER. Comparisons might be wrong.])
   fi
 
-  $2COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", [$]1, [$]2, [$]3) }' <<< "[$]$1CC_VERSION_NUMBER"`
+  $2COMPARABLE_ACTUAL_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", [$]1, [$]2, [$]3, [$]4) }' <<< "[$]$1CC_VERSION_NUMBER"`
 ])
 
 # Check if the configured compiler (C and C++) is of a specific version or
@@ -94,8 +94,8 @@
   # Need to assign to a variable since m4 is blocked from modifying parts in [].
   REFERENCE_VERSION=ARG_VERSION
 
-  if [ [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ]; then
-    AC_MSG_ERROR([Internal error: Cannot compare to ARG_VERSION, only three parts (X.Y.Z) is supported])
+  if [ [[ "$REFERENCE_VERSION" =~ (.*\.){4} ]] ]; then
+    AC_MSG_ERROR([Internal error: Cannot compare to ARG_VERSION, only four parts (W.X.Y.Z) is supported])
   fi
 
   if [ [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ]; then
@@ -103,7 +103,7 @@
   fi
 
   # Version comparison method inspired by http://stackoverflow.com/a/24067243
-  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", [$]1, [$]2, [$]3) }' <<< "$REFERENCE_VERSION"`
+  COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d%05d\n", [$]1, [$]2, [$]3, [$]4) }' <<< "$REFERENCE_VERSION"`
 
   if test [$]ARG_PREFIX[COMPARABLE_ACTUAL_VERSION] -ge $COMPARABLE_REFERENCE_VERSION ; then
     :
@@ -333,9 +333,11 @@
   if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
     # cc -V output typically looks like
     #     cc: Sun C 5.12 Linux_i386 2011/11/16
+    # or
+    #     cc: Studio 12.5 Sun C 5.14 SunOS_sparc 2016/05/31
     COMPILER_VERSION_OUTPUT=`$COMPILER -V 2>&1`
     # Check that this is likely to be the Solaris Studio cc.
-    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.*: Sun $COMPILER_NAME" > /dev/null
+    $ECHO "$COMPILER_VERSION_OUTPUT" | $GREP "^.* Sun $COMPILER_NAME" > /dev/null
     if test $? -ne 0; then
       ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
       AC_MSG_NOTICE([The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler.])
@@ -827,7 +829,7 @@
     BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
     BUILD_SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS"
     BUILD_AR="$AR"
-    
+
     TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS([], [OPENJDK_BUILD_])
   fi
 
@@ -842,36 +844,6 @@
   AC_SUBST(BUILD_AR)
 ])
 
-# Setup legacy variables that are still needed as alternative ways to refer to
-# parts of the toolchain.
-AC_DEFUN_ONCE([TOOLCHAIN_SETUP_LEGACY],
-[
-  if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
-    # For hotspot, we need these in Windows mixed path,
-    # so rewrite them all. Need added .exe suffix.
-    HOTSPOT_CXX="$CXX.exe"
-    HOTSPOT_LD="$LD.exe"
-    HOTSPOT_MT="$MT.exe"
-    HOTSPOT_RC="$RC.exe"
-    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_CXX)
-    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_LD)
-    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_MT)
-    BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(HOTSPOT_RC)
-    AC_SUBST(HOTSPOT_MT)
-    AC_SUBST(HOTSPOT_RC)
-  else
-    HOTSPOT_CXX="$CXX"
-    HOTSPOT_LD="$LD"
-  fi
-  AC_SUBST(HOTSPOT_CXX)
-  AC_SUBST(HOTSPOT_LD)
-
-  if test  "x$TOOLCHAIN_TYPE" = xclang; then
-    USE_CLANG=true
-  fi
-  AC_SUBST(USE_CLANG)
-])
-
 # Do some additional checks on the detected tools.
 AC_DEFUN_ONCE([TOOLCHAIN_MISC_CHECKS],
 [
diff --git a/common/autoconf/toolchain_windows.m4 b/common/autoconf/toolchain_windows.m4
index 4a40fa6..f2304df 100644
--- a/common/autoconf/toolchain_windows.m4
+++ b/common/autoconf/toolchain_windows.m4
@@ -566,7 +566,7 @@
       [path to microsoft C runtime dll (msvcr*.dll) (Windows only) @<:@probed@:>@])])
 
   if test "x$with_msvcr_dll" != x; then
-    # If given explicitely by user, do not probe. If not present, fail directly.
+    # If given explicitly by user, do not probe. If not present, fail directly.
     TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL($MSVCR_NAME, [$with_msvcr_dll], [--with-msvcr-dll])
     if test "x$MSVC_DLL" = x; then
       AC_MSG_ERROR([Could not find a proper $MSVCR_NAME as specified by --with-msvcr-dll])
@@ -589,7 +589,7 @@
 
   if test "x$MSVCP_NAME" != "x"; then
     if test "x$with_msvcp_dll" != x; then
-      # If given explicitely by user, do not probe. If not present, fail directly.
+      # If given explicitly by user, do not probe. If not present, fail directly.
       TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL($MSVCP_NAME, [$with_msvcp_dll], [--with-msvcp-dll])
       if test "x$MSVC_DLL" = x; then
         AC_MSG_ERROR([Could not find a proper $MSVCP_NAME as specified by --with-msvcp-dll])
diff --git a/common/bin/compare.sh b/common/bin/compare.sh
index ba60485..de909e0 100644
--- a/common/bin/compare.sh
+++ b/common/bin/compare.sh
@@ -1295,8 +1295,8 @@
         OTHER_JDK="$OTHER/images/jdk"
         OTHER_JRE="$OTHER/images/jre"
         echo "Selecting jdk images for compare"
-    elif [ -d "$(ls -d $THIS/licensee-src/build/*/images/jdk)" ] \
-        && [ -d "$(ls -d $OTHER/licensee-src/build/*/images/jdk)" ]
+    elif [ -d "$(ls -d $THIS/licensee-src/build/*/images/jdk 2> /dev/null)" ] \
+        && [ -d "$(ls -d $OTHER/licensee-src/build/*/images/jdk 2> /dev/null)" ]
     then
         echo "Selecting licensee images for compare"
         # Simply override the THIS and OTHER dir with the build dir from
diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js
index fa3c574..a40c8b0 100644
--- a/common/conf/jib-profiles.js
+++ b/common/conf/jib-profiles.js
@@ -427,7 +427,7 @@
         jtreg: {
             server: "javare",
             revision: "4.2",
-            build_number: "b03",
+            build_number: "b04",
             checksum_file: "MD5_VALUES",
             file: "jtreg_bin-4.2.zip",
             environment_name: "JT_HOME",
diff --git a/corba/.hgignore b/corba/.hgignore
index 5e6b22f..d782b28 100644
--- a/corba/.hgignore
+++ b/corba/.hgignore
@@ -2,5 +2,4 @@
 ^dist/
 ^webrev
 /nbproject/private/
-^.hgtip
 .DS_Store
diff --git a/corba/.hgtags b/corba/.hgtags
index 9adfbbc..280f13b 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -389,3 +389,4 @@
 d4f1dae174098e799c48948e866054c52e11a186 jdk-9+144
 a44b156ae7f06bf41b9bece30df7775e482395dd jdk-9+145
 ecd74b41ab65bf228837b5bdf99690638d55425c jdk-9+146
+dc49e0922a8e4387cbf8670bbe1dc51c9874b74b jdk-9+147
diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java
index 58cff06..10a26f0 100644
--- a/corba/src/java.corba/share/classes/module-info.java
+++ b/corba/src/java.corba/share/classes/module-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,10 @@
 /**
  * Defines the Java binding of the OMG CORBA APIs, and the RMI-IIOP API.
  */
+@Deprecated(since="9", forRemoval=true)
 module java.corba {
-    requires public java.desktop;
-    requires public java.rmi;
+    requires transitive java.desktop;
+    requires transitive java.rmi;
     requires java.logging;
     requires java.naming;
     requires java.transaction;
@@ -65,14 +66,13 @@
     exports org.omg.PortableServer.portable;
     exports org.omg.SendingContext;
     exports org.omg.stub.java.rmi;
-    exports com.sun.corba.se.impl.util to
-        jdk.rmic;
-    exports com.sun.jndi.cosnaming to
-        java.naming;
-    exports com.sun.jndi.url.corbaname to
-        java.naming;
-    exports com.sun.jndi.url.iiop to
-        java.naming;
-    exports com.sun.jndi.url.iiopname to
-        java.naming;
+
+    // rmic --iiop
+    exports com.sun.corba.se.impl.util to jdk.rmic;
+
+    // JNDI CosNaming provider
+    opens com.sun.jndi.cosnaming to java.naming;  // jndiprovider.properties
+    exports com.sun.jndi.url.corbaname to java.naming;
+    exports com.sun.jndi.url.iiop to java.naming;
+    exports com.sun.jndi.url.iiopname to java.naming;
 }
diff --git a/hotspot/.hgignore b/hotspot/.hgignore
index f7628dd..d3a43d0 100644
--- a/hotspot/.hgignore
+++ b/hotspot/.hgignore
@@ -8,7 +8,6 @@
 ^src/share/tools/IdealGraphVisualizer/dist/
 ^src/share/tools/IdealGraphVisualizer/nbplatform/
 .igv.log
-^.hgtip
 .DS_Store
 ^\.mx.jvmci/env
 ^\.mx.jvmci/.*\.pyc
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index c7fc0f3..4070057 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -549,3 +549,4 @@
 6187b582d02aee38341dc8ce4011906e9b364e9f jdk-9+144
 61e7ea56312351657e69198c503a6f7bf865af83 jdk-9+145
 a82cb5350cad96a0b4de496afebe3ded89f27efa jdk-9+146
+132a72c782071cc11ab25cc7c9ee167c3632fea4 jdk-9+147
diff --git a/hotspot/make/symbols/symbols-unix b/hotspot/make/symbols/symbols-unix
index cee0c5f..90326d2 100644
--- a/hotspot/make/symbols/symbols-unix
+++ b/hotspot/make/symbols/symbols-unix
@@ -190,8 +190,6 @@
 JVM_AddModuleExportsToAllUnnamed
 JVM_AddModulePackage
 JVM_AddReadsModule
-JVM_CanReadModule
 JVM_DefineModule
-JVM_IsExportedToModule
 JVM_SetBootLoaderUnnamedModule
 JVM_GetModuleByPackageName
diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk
index 78e78d7..cdead40 100644
--- a/hotspot/make/test/JtregNative.gmk
+++ b/hotspot/make/test/JtregNative.gmk
@@ -55,6 +55,9 @@
     $(HOTSPOT_TOPDIR)/test/compiler/calls \
     $(HOTSPOT_TOPDIR)/test/compiler/native \
     $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \
+    $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleReads \
+    $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleExportsAndOpens \
+    $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleUsesAndProvides \
     $(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \
     $(HOTSPOT_TOPDIR)/test/compiler/jvmci/jdk.vm.ci.code.test \
     $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetModulesInfo \
@@ -81,6 +84,9 @@
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc
+    BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleReadsTest := -lc
+    BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleExportsAndOpensTest := -lc
+    BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleUsesAndProvidesTest := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassFileLoadHook := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassLoadPrepare := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAThreadStart := -lc
diff --git a/hotspot/src/jdk.vm.ci/share/classes/module-info.java b/hotspot/src/jdk.vm.ci/share/classes/module-info.java
index f1a766e..e62eed3 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/module-info.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/module-info.java
@@ -30,9 +30,7 @@
     uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
 
     provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
-        jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory;
-    provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
-        jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory;
-    provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
+        jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory,
+        jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory,
         jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory;
 }
diff --git a/hotspot/src/share/vm/classfile/moduleEntry.hpp b/hotspot/src/share/vm/classfile/moduleEntry.hpp
index 82f0747..6301d4e 100644
--- a/hotspot/src/share/vm/classfile/moduleEntry.hpp
+++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp
@@ -36,6 +36,8 @@
 #include "utilities/ostream.hpp"
 
 #define UNNAMED_MODULE "Unnamed Module"
+#define JAVAPKG "java/"
+#define JAVAPKG_LEN 5
 
 class ModuleClosure;
 
diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp
index a4cdacc..9c4aa89 100644
--- a/hotspot/src/share/vm/classfile/modules.cpp
+++ b/hotspot/src/share/vm/classfile/modules.cpp
@@ -34,6 +34,7 @@
 #include "classfile/packageEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
@@ -44,6 +45,7 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/reflection.hpp"
+#include "utilities/stringUtils.hpp"
 #include "utilities/utf8.hpp"
 
 static bool verify_module_name(char *module_name) {
@@ -290,6 +292,14 @@
 
   const char* module_version = get_module_version(version);
 
+  oop loader = java_lang_reflect_Module::loader(module_handle());
+  // Make sure loader is not the jdk.internal.reflect.DelegatingClassLoader.
+  if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader is an invalid delegating class loader");
+  }
+  Handle h_loader = Handle(THREAD, loader);
+
   objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
   objArrayHandle packages_h(THREAD, packages_oop);
   int num_packages = (packages_h == NULL ? 0 : packages_h->length());
@@ -310,6 +320,21 @@
                 err_msg("Invalid package name: %s for module: %s",
                         package_name, module_name));
     }
+
+    // Only modules defined to either the boot or platform class loader, can define a "java/" package.
+    if (!h_loader.is_null() &&
+        !SystemDictionary::is_platform_class_loader(h_loader) &&
+        strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
+      const char* class_loader_name = SystemDictionary::loader_name(h_loader());
+      StringUtils::replace_no_expand(package_name, "/", ".");
+      const char* msg_text1 = "Class loader (instance of): ";
+      const char* msg_text2 = " tried to define prohibited package name: ";
+      size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+      char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
+      jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
+    }
+
     Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
     // append_if_missing() returns FALSE if entry already exists.
     if (!pkg_list->append_if_missing(pkg_symbol)) {
@@ -319,20 +344,6 @@
     }
   }
 
-  oop loader = java_lang_reflect_Module::loader(module_handle());
-  // Make sure loader is not the sun.reflect.DelegatingClassLoader.
-  if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-              "Class loader is an invalid delegating class loader");
-  }
-  Handle h_loader = Handle(THREAD, loader);
-
-  // Check that loader is a subclass of java.lang.ClassLoader.
-  if (loader != NULL && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
-              "Class loader is not a subclass of java.lang.ClassLoader");
-  }
-
   ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
   assert(module_table != NULL, "module entry table shouldn't be null");
 
@@ -595,122 +606,6 @@
   }
 }
 
-jboolean Modules::can_read_module(jobject asking_module, jobject target_module, TRAPS) {
-  if (asking_module == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
-               "asking_module is null", JNI_FALSE);
-  }
-
-  ModuleEntry* asking_module_entry = get_module_entry(asking_module, CHECK_false);
-  if (asking_module_entry == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               "asking_module is invalid", JNI_FALSE);
-  }
-
-  // Calling can_read_all_unnamed() with NULL tests if a module is loose.
-  if (target_module == NULL) {
-    return asking_module_entry->can_read_all_unnamed();
-  }
-
-  ModuleEntry* target_module_entry = get_module_entry(target_module, CHECK_false);
-  if (target_module_entry == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               "target_module is invalid", JNI_FALSE);
-  }
-
-  ResourceMark rm(THREAD);
-  log_debug(modules)("can_read_module(): module %s trying to read module %s, allowed = %s",
-                     asking_module_entry->is_named() ?
-                       asking_module_entry->name()->as_C_string() : UNNAMED_MODULE,
-                     target_module_entry->is_named() ?
-                       target_module_entry->name()->as_C_string() : UNNAMED_MODULE,
-                     BOOL_TO_STR(asking_module_entry == target_module_entry ||
-                                 (asking_module_entry->can_read_all_unnamed() &&
-                                  !target_module_entry->is_named()) ||
-                                  asking_module_entry->can_read(target_module_entry)));
-
-  // Return true if:
-  // 1. the modules are the same, or
-  // 2. the asking_module is unnamed (because unnamed modules read everybody), or
-  // 3. the asking_module is loose and the target module is unnamed, or
-  // 4. if can_read() returns true.
-  if (asking_module_entry == target_module_entry ||
-      (asking_module_entry->can_read_all_unnamed() && !target_module_entry->is_named())) {
-    return true;
-  }
-  return asking_module_entry->can_read(target_module_entry);
-}
-
-jboolean Modules::is_exported_to_module(jobject from_module, jstring package,
-                                        jobject to_module, TRAPS) {
-  if (package == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
-               "package is null", JNI_FALSE);
-  }
-  if (from_module == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
-               "from_module is null", JNI_FALSE);
-  }
-  ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK_false);
-  if (from_module_entry == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               "from_module is invalid", JNI_FALSE);
-  }
-  ModuleEntry* to_module_entry;
-  if (to_module == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
-               "to_module is null", JNI_FALSE);
-  }
-  to_module_entry = get_module_entry(to_module, CHECK_false);
-  if (to_module_entry == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               "to_module is invalid", JNI_FALSE);
-  }
-
-  PackageEntry *package_entry = get_package_entry(from_module_entry, package,
-                                                  CHECK_false);
-  ResourceMark rm(THREAD);
-  if (package_entry == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               err_msg("Package not found in from_module: %s",
-                       from_module_entry->is_named() ?
-                         from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
-               JNI_FALSE);
-  }
-  if (package_entry->module() != from_module_entry) {
-    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
-               err_msg("Package: %s found in module %s, not in from_module: %s",
-                       package_entry->name()->as_C_string(),
-                       package_entry->module()->is_named() ?
-                         package_entry->module()->name()->as_C_string() : UNNAMED_MODULE,
-                       from_module_entry->is_named() ?
-                         from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
-               JNI_FALSE);
-  }
-
-  log_debug(modules)("is_exported_to_module: package %s from module %s checking"
-                     " if exported to module %s, exported? = %s",
-                     package_entry->name()->as_C_string(),
-                     from_module_entry->is_named() ?
-                       from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
-                     to_module_entry->is_named() ?
-                       to_module_entry->name()->as_C_string() : UNNAMED_MODULE,
-                     BOOL_TO_STR(!from_module_entry->is_named() ||
-                       package_entry->is_unqual_exported() ||
-                       from_module_entry == to_module_entry ||
-                       package_entry->is_qexported_to(to_module_entry)));
-
-  // Return true if:
-  // 1. from_module is unnamed because unnamed modules export all their packages (by default), or
-  // 2. if the package is unqualifiedly exported, or
-  // 3. if the modules are the same, or
-  // 4. if the package is exported to to_module
-  return (!from_module_entry->is_named() ||
-          package_entry->is_unqual_exported() ||
-          from_module_entry == to_module_entry ||
-          package_entry->is_qexported_to(to_module_entry));
-}
-
 // This method is called by JFR and JNI.
 jobject Modules::get_module(jclass clazz, TRAPS) {
   assert(ModuleEntryTable::javabase_defined(), "Attempt to call get_module before java.base is defined");
@@ -860,11 +755,27 @@
               err_msg("Invalid package name: %s", package_name));
   }
 
+  ClassLoaderData *loader_data = module_entry->loader_data();
+
+  // Only modules defined to either the boot or platform class loader, can define a "java/" package.
+  if (!loader_data->is_the_null_class_loader_data() &&
+      !loader_data->is_platform_class_loader_data() &&
+      strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
+    const char* class_loader_name = SystemDictionary::loader_name(loader_data);
+    StringUtils::replace_no_expand(package_name, "/", ".");
+    const char* msg_text1 = "Class loader (instance of): ";
+    const char* msg_text2 = " tried to define prohibited package name: ";
+    size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+    char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
+    jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
+  }
+
   log_debug(modules)("add_module_package(): Adding package %s to module %s",
                      package_name, module_entry->name()->as_C_string());
 
   TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
-  PackageEntryTable* package_table = module_entry->loader_data()->packages();
+  PackageEntryTable* package_table = loader_data->packages();
   assert(package_table != NULL, "Missing package_table");
 
   bool pkg_exists = false;
diff --git a/hotspot/src/share/vm/classfile/modules.hpp b/hotspot/src/share/vm/classfile/modules.hpp
index 2d0c331..25d02bf 100644
--- a/hotspot/src/share/vm/classfile/modules.hpp
+++ b/hotspot/src/share/vm/classfile/modules.hpp
@@ -93,24 +93,6 @@
   // module does not exist.
   static void add_reads_module(jobject from_module, jobject to_module, TRAPS);
 
-  // can_read_module returns TRUE if module asking_module can read module target_module,
-  // or if they are the same module, or if the asking_module is loose and target_module
-  // is null.
-  //
-  // Throws IllegalArgumentException if:
-  // * either asking_module or target_module is not a java.lang.reflect.Module
-  static jboolean can_read_module(jobject asking_module, jobject target_module, TRAPS);
-
-  // If package is valid then this returns TRUE if module from_module exports
-  // package to module to_module, if from_module and to_module are the same
-  // module, or if package is exported without qualification.
-  //
-  // IllegalArgumentException is throw if:
-  // * Either to_module or from_module does not exist
-  // * package is syntactically incorrect
-  // * package is not in from_module
-  static jboolean is_exported_to_module(jobject from_module, jstring package, jobject to_module, TRAPS);
-
   // Return the java.lang.reflect.Module object for this class object.
   static jobject get_module(jclass clazz, TRAPS);
 
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index fd3b3fe..31e3519 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -451,8 +451,6 @@
   template(loader_name,                               "loader")                                   \
   template(module_name,                               "module")                                   \
   template(getModule_name,                            "getModule")                                \
-  template(addReads_name,                             "addReads")                                 \
-  template(addReads_signature,                        "(Ljava/lang/reflect/Module;Ljava/lang/reflect/Module;)V")           \
   template(input_stream_void_signature,               "(Ljava/io/InputStream;)V")                 \
   template(definePackage_name,                        "definePackage")                            \
   template(definePackage_signature,                   "(Ljava/lang/String;Ljava/lang/reflect/Module;)Ljava/lang/Package;") \
@@ -645,6 +643,15 @@
   /* JVMTI/java.lang.instrument support and VM Attach mechanism */                                                \
   template(jdk_internal_module_Modules,                "jdk/internal/module/Modules")                             \
   template(jdk_internal_vm_VMSupport,                  "jdk/internal/vm/VMSupport")                               \
+  template(addReads_name,                              "addReads")                                                \
+  template(addReads_signature,                         "(Ljava/lang/reflect/Module;Ljava/lang/reflect/Module;)V") \
+  template(addExports_name,                            "addExports")                                              \
+  template(addOpens_name,                              "addOpens")                                                \
+  template(addExports_signature,                       "(Ljava/lang/reflect/Module;Ljava/lang/String;Ljava/lang/reflect/Module;)V") \
+  template(addUses_name,                               "addUses")                                                 \
+  template(addUses_signature,                          "(Ljava/lang/reflect/Module;Ljava/lang/Class;)V")          \
+  template(addProvides_name,                           "addProvides")                                             \
+  template(addProvides_signature,                      "(Ljava/lang/reflect/Module;Ljava/lang/Class;Ljava/lang/Class;)V") \
   template(transformedByAgent_name,                    "transformedByAgent")                                      \
   template(transformedByAgent_signature,               "(Ljava/lang/reflect/Module;)V")                           \
   template(appendToClassPathForInstrumentation_name,   "appendToClassPathForInstrumentation")                     \
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index 7e6c3c8..32c2245 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -26,6 +26,7 @@
 #include "classfile/classFileParser.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "classfile/verifier.hpp"
@@ -2383,18 +2384,17 @@
 
 // Only boot and platform class loaders can define classes in "java/" packages.
 void InstanceKlass::check_prohibited_package(Symbol* class_name,
-                                                Handle class_loader,
-                                                TRAPS) {
-  const char* javapkg = "java/";
+                                             Handle class_loader,
+                                             TRAPS) {
   ResourceMark rm(THREAD);
   if (!class_loader.is_null() &&
       !SystemDictionary::is_platform_class_loader(class_loader) &&
       class_name != NULL &&
-      strncmp(class_name->as_C_string(), javapkg, strlen(javapkg)) == 0) {
+      strncmp(class_name->as_C_string(), JAVAPKG, JAVAPKG_LEN) == 0) {
     TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK);
     assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
     char* name = pkg_name->as_C_string();
-    const char* class_loader_name = InstanceKlass::cast(class_loader()->klass())->name()->as_C_string();
+    const char* class_loader_name = SystemDictionary::loader_name(class_loader());
     StringUtils::replace_no_expand(name, "/", ".");
     const char* msg_text1 = "Class loader (instance of): ";
     const char* msg_text2 = " tried to load prohibited package name: ";
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index bb67d13..f519e5e 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -3475,40 +3475,6 @@
 JNI_END
 
 
-JNI_ENTRY(void, jni_AddModuleReads(JNIEnv* env, jobject m1, jobject m2))
-  JNIWrapper("AddModuleReads");
-  if (m1 == NULL || m2 == NULL) {
-    THROW(vmSymbols::java_lang_NullPointerException());
-  }
-  JavaValue result(T_VOID);
-  Handle m1_h(THREAD, JNIHandles::resolve(m1));
-  if (!java_lang_reflect_Module::is_instance(m1_h())) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad m1 object");
-  }
-  Handle m2_h(THREAD, JNIHandles::resolve(m2));
-  if (!java_lang_reflect_Module::is_instance(m2_h())) {
-    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad m2 object");
-  }
-  JavaCalls::call_static(&result,
-                         KlassHandle(THREAD, SystemDictionary::module_Modules_klass()),
-                         vmSymbols::addReads_name(),
-                         vmSymbols::addReads_signature(),
-                         m1_h,
-                         m2_h,
-                         THREAD);
-JNI_END
-
-
-JNI_ENTRY(jboolean, jni_CanReadModule(JNIEnv* env, jobject m1, jobject m2))
-  JNIWrapper("CanReadModule");
-  if (m1 == NULL || m2 == NULL) {
-    THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
-  }
-  jboolean res = Modules::can_read_module(m1, m2, CHECK_false);
-  return res;
-JNI_END
-
-
 // Structure containing all jni functions
 struct JNINativeInterface_ jni_NativeInterface = {
     NULL,
@@ -3792,9 +3758,7 @@
 
     // Module features
 
-    jni_GetModule,
-    jni_AddModuleReads,
-    jni_CanReadModule
+    jni_GetModule
 };
 
 
diff --git a/hotspot/src/share/vm/prims/jni.h b/hotspot/src/share/vm/prims/jni.h
index 9699688..d5de88d 100644
--- a/hotspot/src/share/vm/prims/jni.h
+++ b/hotspot/src/share/vm/prims/jni.h
@@ -770,12 +770,6 @@
 
     jobject (JNICALL *GetModule)
        (JNIEnv* env, jclass clazz);
-
-    void (JNICALL *AddModuleReads)
-       (JNIEnv* env, jobject m1, jobject m2);
-
-    jboolean (JNICALL *CanReadModule)
-       (JNIEnv* env, jobject m1, jobject m2);
 };
 
 /*
@@ -1874,14 +1868,6 @@
         return functions->GetModule(this, clazz);
     }
 
-    void AddModuleReads(jobject fromModule, jobject sourceModule) {
-        functions->AddModuleReads(this, fromModule, sourceModule);
-    }
-
-    jboolean CanReadModule(jobject askingModule, jobject sourceModule) {
-        return functions->CanReadModule(this, askingModule, sourceModule);
-    }
-
 #endif /* __cplusplus */
 };
 
diff --git a/hotspot/src/share/vm/prims/jniCheck.cpp b/hotspot/src/share/vm/prims/jniCheck.cpp
index d6b7035..ea80b5b 100644
--- a/hotspot/src/share/vm/prims/jniCheck.cpp
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp
@@ -2001,37 +2001,6 @@
     return result;
 JNI_END
 
-JNI_ENTRY_CHECKED(void,
-  checked_jni_AddModuleReads(JNIEnv *env,
-                             jobject fromModule,
-                             jobject sourceModule))
-    functionEnter(thr);
-    IN_VM(
-      jniCheck::validate_object(thr, fromModule);
-      if (sourceModule != NULL) {
-        jniCheck::validate_object(thr, sourceModule);
-      }
-    )
-    UNCHECKED()->AddModuleReads(env,fromModule,sourceModule);
-    functionExit(thr);
-JNI_END
-
-JNI_ENTRY_CHECKED(jboolean,
-  checked_jni_CanReadModule(JNIEnv *env,
-                            jobject askingModule,
-                            jobject sourceModule))
-    functionEnter(thr);
-    IN_VM(
-      jniCheck::validate_object(thr, askingModule);
-      if (sourceModule != NULL) {
-        jniCheck::validate_object(thr, sourceModule);
-      }
-    )
-    jboolean result = UNCHECKED()->CanReadModule(env,askingModule,sourceModule);
-    functionExit(thr);
-    return result;
-JNI_END
-
 /*
  * Structure containing all checked jni functions
  */
@@ -2317,9 +2286,7 @@
 
     // Module Features
 
-    checked_jni_GetModule,
-    checked_jni_AddModuleReads,
-    checked_jni_CanReadModule
+    checked_jni_GetModule
 };
 
 
diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp
index 51bc575..6a1b4dd 100644
--- a/hotspot/src/share/vm/prims/jvm.cpp
+++ b/hotspot/src/share/vm/prims/jvm.cpp
@@ -1008,8 +1008,8 @@
 
 // Module support //////////////////////////////////////////////////////////////////////////////
 
-JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
-                                 jobjectArray packages))
+JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
+                                 jstring location, jobjectArray packages))
   JVMWrapper("JVM_DefineModule");
   Modules::define_module(module, version, location, packages, CHECK);
 JVM_END
@@ -1039,16 +1039,6 @@
   Modules::add_reads_module(from_module, source_module, CHECK);
 JVM_END
 
-JVM_ENTRY(jboolean, JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module))
-  JVMWrapper("JVM_CanReadModule");
-  return Modules::can_read_module(asking_module, source_module, THREAD);
-JVM_END
-
-JVM_ENTRY(jboolean, JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
-  JVMWrapper("JVM_IsExportedToModule");
-  return Modules::is_exported_to_module(from_module, package, to_module, THREAD);
-JVM_END
-
 JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
   JVMWrapper("JVM_AddModulePackage");
   Modules::add_module_package(module, package, CHECK);
diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h
index 47bf5a0..c713645 100644
--- a/hotspot/src/share/vm/prims/jvm.h
+++ b/hotspot/src/share/vm/prims/jvm.h
@@ -413,8 +413,8 @@
  */
 
 JNIEXPORT void JNICALL
-JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
-                 jobjectArray packages);
+JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
+                 jstring location, jobjectArray packages);
 
 JNIEXPORT void JNICALL
 JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
@@ -431,12 +431,6 @@
 JNIEXPORT void JNICALL
 JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
 
-JNIEXPORT jboolean JNICALL
-JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
-
 JNIEXPORT void JNICALL
 JVM_AddModulePackage(JNIEnv* env,  jobject module, jstring package);
 
diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml
index bcbfc99..28144da 100644
--- a/hotspot/src/share/vm/prims/jvmti.xml
+++ b/hotspot/src/share/vm/prims/jvmti.xml
@@ -863,14 +863,12 @@
   </intro>
 
 <intro id="bcimodules" label="Bytecode Instrumentation of code in modules">
-  Agents that instrument code in named modules may need to arrange for those
-  modules to read other modules. If code is instrumented to invoke a method
-  in a support class in another module, then the module of the instrumented
-  code should read the module of the supporting class. Furthermore, the
-  supporting class will only be accessible to the instrumented code if
-  it is <code>public</code> and in a package that is exported by its module.
-  Agents can use the JNI functions <code>CanReadModule</code> and
-  <code>AddModuleReads</code> to test and update a module to read another.
+  Agents can use the functions <functionlink id="AddModuleReads"/>,
+  <functionlink id="AddModuleExports"/>, <functionlink id="AddModuleOpens"/>,
+  <functionlink id="AddModuleUses"/> and <functionlink id="AddModuleProvides"/>
+  to update a module to expand the set of modules that it reads, the set of
+  packages that it exports or opens to other modules, or the services that it
+  uses and provides.
   <p/>
   As an aid to agents that deploy supporting classes on the search path of
   the bootstrap class loader, or the search path of the class loader that
@@ -6561,6 +6559,227 @@
         </error>
       </errors>
     </function>
+
+    <function id="AddModuleReads" num="94" since="9">
+      <synopsis>Add Module Reads</synopsis>
+      <description>
+         Update a module to read another module. This function is a no-op
+         when <paramlink id="module"></paramlink> is an unnamed module.
+         This function facilitates the instrumentation of code
+         in named modules where that instrumentation requires
+         expanding the set of modules that a module reads.
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+        <param id="module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module to update.
+          </description>
+        </param>
+        <param id="to_module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The additional module to read.
+          </description>
+        </param>
+      </parameters>
+      <errors>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="module"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="to_module"></paramlink> is not a module object.
+        </error>
+      </errors>
+    </function>
+
+    <function id="AddModuleExports" num="95" since="9">
+      <synopsis>Add Module Exports</synopsis>
+      <description>
+         Update a module to export a package to another module.
+         This function is a no-op when <paramlink id="module"></paramlink>
+         is an unnamed module or an open module.
+         This function facilitates the instrumentation of code
+         in named modules where that instrumentation requires
+         expanding the set of packages that a module exports.
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+        <param id="module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module to update.
+          </description>
+        </param>
+        <param id="pkg_name">
+          <inbuf><char/></inbuf>
+          <description>
+            The exported package name.
+          </description>
+        </param>
+        <param id="to_module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module the package is exported to.
+            If the <code>to_module</code> is not a subclass of
+            <code>java.lang.reflect.Module</code> this function returns
+            <errorlink id="JVMTI_ERROR_INVALID_MODULE"></errorlink>.
+          </description>
+        </param>
+      </parameters>
+      <errors>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="module"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="to_modules"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_ILLEGAL_ARGUMENT">
+          If the package <paramlink id="pkg_name"></paramlink>
+          does not belong to the module.
+        </error>
+      </errors>
+    </function>
+
+    <function id="AddModuleOpens" num="96" since="9">
+      <synopsis>Add Module Opens</synopsis>
+      <description>
+         Update a module to open a package to another module.
+         This function is a no-op when <paramlink id="module"></paramlink>
+         is an unnamed module or an open module.
+         This function facilitates the instrumentation of code
+         in modules where that instrumentation requires
+         expanding the set of packages that a module opens to
+         other modules.
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+        <param id="module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module to update.
+          </description>
+        </param>
+        <param id="pkg_name">
+          <inbuf><char/></inbuf>
+          <description>
+            The package name of the package to open.
+          </description>
+        </param>
+        <param id="to_module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module with the package to open.
+            If the <code>to_module</code> is not a subclass of
+            <code>java.lang.reflect.Module</code> this function returns
+            <errorlink id="JVMTI_ERROR_INVALID_MODULE"></errorlink>.
+          </description>
+        </param>
+      </parameters>
+      <errors>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="module"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="to_modules"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_ILLEGAL_ARGUMENT">
+          If the package <paramlink id="pkg_name"></paramlink>
+          does not belong to the module.
+        </error>
+      </errors>
+    </function>
+
+    <function id="AddModuleUses" num="97" since="9">
+      <synopsis>Add Module Uses</synopsis>
+      <description>
+         Updates a module to add a service to the set of services that
+         a module uses. This function is a no-op when the module
+         is an unnamed module.
+         This function facilitates the instrumentation of code
+         in named modules where that instrumentation requires
+         expanding the set of services that a module is using.
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+        <param id="module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module to update.
+          </description>
+        </param>
+        <param id="service">
+          <ptrtype><jclass/></ptrtype>
+          <description>
+            The service to use.
+          </description>
+        </param>
+      </parameters>
+      <errors>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="module"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_INVALID_CLASS">
+          If <paramlink id="service"></paramlink> is not a class object.
+        </error>
+      </errors>
+    </function>
+
+    <function id="AddModuleProvides" num="98" since="9">
+      <synopsis>Add Module Provides</synopsis>
+      <description>
+         Updates a module to add a service to the set of services that
+         a module provides. This function is a no-op when the module
+         is an unnamed module.
+         This function facilitates the instrumentation of code
+         in named modules where that instrumentation requires
+         changes to the services that are provided.
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+        <param id="module">
+          <ptrtype><jobject/></ptrtype>
+          <description>
+            The module to update.
+          </description>
+        </param>
+        <param id="service">
+          <ptrtype><jclass/></ptrtype>
+          <description>
+            The service to provide.
+          </description>
+        </param>
+        <param id="impl_class">
+          <ptrtype><jclass/></ptrtype>
+          <description>
+            The implementation class for the provided service.
+          </description>
+        </param>
+      </parameters>
+      <errors>
+        <error id="JVMTI_ERROR_INVALID_MODULE">
+          If <paramlink id="module"></paramlink> is not a module object.
+        </error>
+        <error id="JVMTI_ERROR_INVALID_CLASS">
+          If <paramlink id="service"></paramlink> is not a class object.
+        </error>
+        <error id="JVMTI_ERROR_INVALID_CLASS">
+          If <paramlink id="impl_class"></paramlink> is not a class object.
+        </error>
+      </errors>
+    </function>
+
   </category>
 
   <category id="class" label="Class">
@@ -11371,6 +11590,9 @@
     <errorid id="JVMTI_ERROR_INVALID_FIELDID" num="25">
       Invalid field.
     </errorid>
+    <errorid id="JVMTI_ERROR_INVALID_MODULE" num="26">
+      Invalid module.
+    </errorid>
     <errorid id="JVMTI_ERROR_INVALID_METHODID" num="23">
       Invalid method.
     </errorid>
@@ -14492,17 +14714,17 @@
   <change date="19 June 2013" version="1.2.3">
       Added support for statically linked agents.
   </change>
-  <change date="5 July 2016" version="9.0.0">
+  <change date="13 October 2016" version="9.0.0">
       Support for modules:
        - The majorversion is 9 now
        - The ClassFileLoadHook events are not sent during the primordial phase anymore.
-       - Add new function GetAllModules
-       - Add new capability can_generate_early_vmstart
        - Allow CompiledMethodLoad events at start phase
-       - Add new capability can_generate_early_class_hook_events
-       - Add new function GetNamedModule
-  </change>
-  <change date="16 August 2016" version="9.0.0">
+       - Add new capabilities:
+          - can_generate_early_vmstart
+          - can_generate_early_class_hook_events
+       - Add new functions:
+          - GetAllModules
+          - AddModuleReads, AddModuleExports, AddModuleOpens, AddModuleUses, AddModuleProvides
       Clarified can_redefine_any_classes, can_retransform_any_classes and IsModifiableClass API to
       disallow some implementation defined classes.
   </change>
diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp
index 3b8ce65..f9dc315 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp
@@ -227,6 +227,119 @@
 } /* end GetNamedModule */
 
 
+// module - pre-checked for NULL
+// to_module - pre-checked for NULL
+jvmtiError
+JvmtiEnv::AddModuleReads(jobject module, jobject to_module) {
+  JavaThread* THREAD = JavaThread::current();
+
+  // check module
+  Handle h_module(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(h_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  // check to_module
+  Handle h_to_module(THREAD, JNIHandles::resolve(to_module));
+  if (!java_lang_reflect_Module::is_instance(h_to_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  return JvmtiExport::add_module_reads(h_module, h_to_module, THREAD);
+} /* end AddModuleReads */
+
+
+// module - pre-checked for NULL
+// pkg_name - pre-checked for NULL
+// to_module - pre-checked for NULL
+jvmtiError
+JvmtiEnv::AddModuleExports(jobject module, const char* pkg_name, jobject to_module) {
+  JavaThread* THREAD = JavaThread::current();
+  Handle h_pkg = java_lang_String::create_from_str(pkg_name, THREAD);
+
+  // check module
+  Handle h_module(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(h_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  // check to_module
+  Handle h_to_module(THREAD, JNIHandles::resolve(to_module));
+  if (!java_lang_reflect_Module::is_instance(h_to_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  return JvmtiExport::add_module_exports(h_module, h_pkg, h_to_module, THREAD);
+} /* end AddModuleExports */
+
+
+// module - pre-checked for NULL
+// pkg_name - pre-checked for NULL
+// to_module - pre-checked for NULL
+jvmtiError
+JvmtiEnv::AddModuleOpens(jobject module, const char* pkg_name, jobject to_module) {
+  JavaThread* THREAD = JavaThread::current();
+  Handle h_pkg = java_lang_String::create_from_str(pkg_name, THREAD);
+
+  // check module
+  Handle h_module(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(h_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  // check to_module
+  Handle h_to_module(THREAD, JNIHandles::resolve(to_module));
+  if (!java_lang_reflect_Module::is_instance(h_to_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  return JvmtiExport::add_module_opens(h_module, h_pkg, h_to_module, THREAD);
+} /* end AddModuleOpens */
+
+
+// module - pre-checked for NULL
+// service - pre-checked for NULL
+jvmtiError
+JvmtiEnv::AddModuleUses(jobject module, jclass service) {
+  JavaThread* THREAD = JavaThread::current();
+
+  // check module
+  Handle h_module(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(h_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  // check service
+  Handle h_service(THREAD, JNIHandles::resolve_external_guard(service));
+  if (!java_lang_Class::is_instance(h_service()) ||
+      java_lang_Class::is_primitive(h_service())) {
+    return JVMTI_ERROR_INVALID_CLASS;
+  }
+  return JvmtiExport::add_module_uses(h_module, h_service, THREAD);
+} /* end AddModuleUses */
+
+
+// module - pre-checked for NULL
+// service - pre-checked for NULL
+// impl_class - pre-checked for NULL
+jvmtiError
+JvmtiEnv::AddModuleProvides(jobject module, jclass service, jclass impl_class) {
+  JavaThread* THREAD = JavaThread::current();
+
+  // check module
+  Handle h_module(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(h_module())) {
+    return JVMTI_ERROR_INVALID_MODULE;
+  }
+  // check service
+  Handle h_service(THREAD, JNIHandles::resolve_external_guard(service));
+  if (!java_lang_Class::is_instance(h_service()) ||
+      java_lang_Class::is_primitive(h_service())) {
+    return JVMTI_ERROR_INVALID_CLASS;
+  }
+  // check impl_class
+  Handle h_impl_class(THREAD, JNIHandles::resolve_external_guard(impl_class));
+  if (!java_lang_Class::is_instance(h_impl_class()) ||
+      java_lang_Class::is_primitive(h_impl_class())) {
+    return JVMTI_ERROR_INVALID_CLASS;
+  }
+  return JvmtiExport::add_module_provides(h_module, h_service, h_impl_class, THREAD);
+} /* end AddModuleProvides */
+
+
   //
   // Class functions
   //
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp
index a388f29..6911039 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp
@@ -434,6 +434,165 @@
   }
 }
 
+jvmtiError
+JvmtiExport::add_module_reads(Handle module, Handle to_module, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return JVMTI_ERROR_NONE; // extra safety
+  }
+  assert(!module.is_null(), "module should always be set");
+  assert(!to_module.is_null(), "to_module should always be set");
+
+  // Invoke the addReads method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::addReads_name(),
+                         vmSymbols::addReads_signature(),
+                         module,
+                         to_module,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    LogTarget(Trace, jvmti) log;
+    LogStreamCHeap log_stream(log);
+    java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
+    log_stream.cr();
+    CLEAR_PENDING_EXCEPTION;
+    return JVMTI_ERROR_INTERNAL;
+  }
+  return JVMTI_ERROR_NONE;
+}
+
+jvmtiError
+JvmtiExport::add_module_exports(Handle module, Handle pkg_name, Handle to_module, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return JVMTI_ERROR_NONE; // extra safety
+  }
+  assert(!module.is_null(), "module should always be set");
+  assert(!to_module.is_null(), "to_module should always be set");
+  assert(!pkg_name.is_null(), "pkg_name should always be set");
+
+  // Invoke the addExports method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::addExports_name(),
+                         vmSymbols::addExports_signature(),
+                         module,
+                         pkg_name,
+                         to_module,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
+    LogTarget(Trace, jvmti) log;
+    LogStreamCHeap log_stream(log);
+    java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
+    log_stream.cr();
+    CLEAR_PENDING_EXCEPTION;
+    if (ex_name == vmSymbols::java_lang_IllegalArgumentException()) {
+      return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+    }
+    return JVMTI_ERROR_INTERNAL;
+  }
+  return JVMTI_ERROR_NONE;
+}
+
+jvmtiError
+JvmtiExport::add_module_opens(Handle module, Handle pkg_name, Handle to_module, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return JVMTI_ERROR_NONE; // extra safety
+  }
+  assert(!module.is_null(), "module should always be set");
+  assert(!to_module.is_null(), "to_module should always be set");
+  assert(!pkg_name.is_null(), "pkg_name should always be set");
+
+  // Invoke the addOpens method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::addOpens_name(),
+                         vmSymbols::addExports_signature(),
+                         module,
+                         pkg_name,
+                         to_module,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
+    LogTarget(Trace, jvmti) log;
+    LogStreamCHeap log_stream(log);
+    java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
+    log_stream.cr();
+    CLEAR_PENDING_EXCEPTION;
+    if (ex_name == vmSymbols::java_lang_IllegalArgumentException()) {
+      return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+    }
+    return JVMTI_ERROR_INTERNAL;
+  }
+  return JVMTI_ERROR_NONE;
+}
+
+jvmtiError
+JvmtiExport::add_module_uses(Handle module, Handle service, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return JVMTI_ERROR_NONE; // extra safety
+  }
+  assert(!module.is_null(), "module should always be set");
+  assert(!service.is_null(), "service should always be set");
+
+  // Invoke the addUses method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::addUses_name(),
+                         vmSymbols::addUses_signature(),
+                         module,
+                         service,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    LogTarget(Trace, jvmti) log;
+    LogStreamCHeap log_stream(log);
+    java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
+    log_stream.cr();
+    CLEAR_PENDING_EXCEPTION;
+    return JVMTI_ERROR_INTERNAL;
+  }
+  return JVMTI_ERROR_NONE;
+}
+
+jvmtiError
+JvmtiExport::add_module_provides(Handle module, Handle service, Handle impl_class, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return JVMTI_ERROR_NONE; // extra safety
+  }
+  assert(!module.is_null(), "module should always be set");
+  assert(!service.is_null(), "service should always be set");
+  assert(!impl_class.is_null(), "impl_class should always be set");
+
+  // Invoke the addProvides method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::addProvides_name(),
+                         vmSymbols::addProvides_signature(),
+                         module,
+                         service,
+                         impl_class,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    LogTarget(Trace, jvmti) log;
+    LogStreamCHeap log_stream(log);
+    java_lang_Throwable::print(PENDING_EXCEPTION, &log_stream);
+    log_stream.cr();
+    CLEAR_PENDING_EXCEPTION;
+    return JVMTI_ERROR_INTERNAL;
+  }
+  return JVMTI_ERROR_NONE;
+}
+
 void
 JvmtiExport::decode_version_values(jint version, int * major, int * minor,
                                    int * micro) {
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp
index 6b11139..d280f21 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp
@@ -218,6 +218,21 @@
   // Add read edges to the unnamed modules of the bootstrap and app class loaders
   static void add_default_read_edges(Handle h_module, TRAPS) NOT_JVMTI_RETURN;
 
+  // Add a read edge to the module
+  static jvmtiError add_module_reads(Handle module, Handle to_module, TRAPS);
+
+  // Updates a module to export a package
+  static jvmtiError add_module_exports(Handle module, Handle pkg_name, Handle to_module, TRAPS);
+
+  // Updates a module to open a package
+  static jvmtiError add_module_opens(Handle module, Handle pkg_name, Handle to_module, TRAPS);
+
+  // Add a used service to the module
+  static jvmtiError add_module_uses(Handle module, Handle service, TRAPS);
+
+  // Add a service provider to the module
+  static jvmtiError add_module_provides(Handle module, Handle service, Handle impl_class, TRAPS);
+
   // let JVMTI know that the JVM_OnLoad code is running
   static void enter_onload_phase() NOT_JVMTI_RETURN;
 
diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp
index 6ef4f96..ba4f6b8 100644
--- a/hotspot/src/share/vm/prims/whitebox.cpp
+++ b/hotspot/src/share/vm/prims/whitebox.cpp
@@ -1415,14 +1415,6 @@
   Modules::add_reads_module(from_module, source_module, CHECK);
 WB_END
 
-WB_ENTRY(jboolean, WB_CanReadModule(JNIEnv* env, jobject o, jobject asking_module, jobject source_module))
-  return Modules::can_read_module(asking_module, source_module, THREAD);
-WB_END
-
-WB_ENTRY(jboolean, WB_IsExportedToModule(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
-  return Modules::is_exported_to_module(from_module, package, to_module, THREAD);
-WB_END
-
 WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
   Modules::add_module_package(module, package, CHECK);
 WB_END
@@ -1866,10 +1858,6 @@
                                                       (void*)&WB_AddModuleExports },
   {CC"AddReadsModule",     CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
                                                       (void*)&WB_AddReadsModule },
-  {CC"CanReadModule",      CC"(Ljava/lang/Object;Ljava/lang/Object;)Z",
-                                                      (void*)&WB_CanReadModule },
-  {CC"IsExportedToModule", CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z",
-                                                      (void*)&WB_IsExportedToModule },
   {CC"AddModulePackage",   CC"(Ljava/lang/Object;Ljava/lang/String;)V",
                                                       (void*)&WB_AddModulePackage },
   {CC"GetModuleByPackageName", CC"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index b02fa54..f9f1e23 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -170,6 +170,8 @@
 #define ADDEXPORTS_LEN 10
 #define ADDREADS "addreads"
 #define ADDREADS_LEN 8
+#define ADDOPENS "addopens"
+#define ADDOPENS_LEN 8
 #define PATCH "patch"
 #define PATCH_LEN 5
 #define ADDMODS "addmods"
@@ -196,6 +198,7 @@
     const char* property_suffix = property + MODULE_PROPERTY_PREFIX_LEN;
     if (matches_property_suffix(property_suffix, ADDEXPORTS, ADDEXPORTS_LEN) ||
         matches_property_suffix(property_suffix, ADDREADS, ADDREADS_LEN) ||
+        matches_property_suffix(property_suffix, ADDOPENS, ADDOPENS_LEN) ||
         matches_property_suffix(property_suffix, PATCH, PATCH_LEN) ||
         matches_property_suffix(property_suffix, ADDMODS, ADDMODS_LEN) ||
         matches_property_suffix(property_suffix, LIMITMODS, LIMITMODS_LEN) ||
@@ -2555,6 +2558,7 @@
 
 unsigned int addreads_count = 0;
 unsigned int addexports_count = 0;
+unsigned int addopens_count = 0;
 unsigned int addmods_count = 0;
 unsigned int patch_mod_count = 0;
 
@@ -2809,6 +2813,10 @@
       if (!create_numbered_property("jdk.module.addexports", tail, addexports_count++)) {
         return JNI_ENOMEM;
       }
+    } else if (match_option(option, "--add-opens=", &tail)) {
+      if (!create_numbered_property("jdk.module.addopens", tail, addopens_count++)) {
+        return JNI_ENOMEM;
+      }
     } else if (match_option(option, "--add-modules=", &tail)) {
       if (!create_numbered_property("jdk.module.addmods", tail, addmods_count++)) {
         return JNI_ENOMEM;
diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp
index 5c544b4..5874699 100644
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp
@@ -285,6 +285,14 @@
 }
 
 
+void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS) {
+  JavaCallArguments args; // One oop argument
+  args.push_oop(arg1);
+  args.push_oop(arg2);
+  args.push_oop(arg3);
+  call_static(result, klass, name, signature, &args, CHECK);
+}
+
 // -------------------------------------------------
 // Implementation of JavaCalls (low level)
 
diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp
index dd67b7e..efe1f8b 100644
--- a/hotspot/src/share/vm/runtime/javaCalls.hpp
+++ b/hotspot/src/share/vm/runtime/javaCalls.hpp
@@ -210,6 +210,7 @@
   static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
   static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
   static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
+  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, Handle arg3, TRAPS);
 
   // Low-level interface
   static void call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS);
diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT
index 4fe2b2a..cce42af 100644
--- a/hotspot/test/TEST.ROOT
+++ b/hotspot/test/TEST.ROOT
@@ -47,8 +47,8 @@
     vm.gc.ConcMarkSweep \
     vm.debug
 
-# Tests using jtreg 4.2 b03 features
-requiredVersion=4.2 b03
+# Tests using jtreg 4.2 b04 features
+requiredVersion=4.2 b04
 
 # Path to libraries in the topmost test directory. This is needed so @library
 # does not need ../../ notation to reach them
diff --git a/hotspot/test/compiler/c2/Test7190310_unsafe.java b/hotspot/test/compiler/c2/Test7190310_unsafe.java
index fb2b6f9..5bb7d75 100644
--- a/hotspot/test/compiler/c2/Test7190310_unsafe.java
+++ b/hotspot/test/compiler/c2/Test7190310_unsafe.java
@@ -25,7 +25,8 @@
  * @test
  * @bug 7190310
  * @summary Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
+ * @modules java.base/java.lang.ref:open
  *
  * @run main/othervm -Xbatch compiler.c2.Test7190310_unsafe
  */
diff --git a/hotspot/test/compiler/codegen/Test8011901.java b/hotspot/test/compiler/codegen/Test8011901.java
index 6a865c1..c7c40ba5 100644
--- a/hotspot/test/compiler/codegen/Test8011901.java
+++ b/hotspot/test/compiler/codegen/Test8011901.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8011901
  * @summary instruct xaddL_no_res shouldn't allow 64 bit constants.
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main/othervm -XX:-BackgroundCompilation compiler.codegen.Test8011901
  */
diff --git a/hotspot/test/compiler/escapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java b/hotspot/test/compiler/escapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java
index 2701512..d9b2f49 100644
--- a/hotspot/test/compiler/escapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java
+++ b/hotspot/test/compiler/escapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8038048
  * @summary assert(null_obj->escape_state() == PointsToNode::NoEscape,etc)
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DoEscapeAnalysis
  *      -XX:-TieredCompilation -Xbatch
diff --git a/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java b/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java
index b524ca4..42e312c 100644
--- a/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java
+++ b/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java
@@ -27,7 +27,8 @@
  * @bug 8130150 8131779 8139907
  * @summary Verify that the Montgomery multiply and square intrinsic works and correctly checks their arguments.
  * @requires vm.flavor == "server"
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.math:open
  * @library /test/lib
  *
  * @build sun.hotspot.WhiteBox
diff --git a/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java
index 388643c..fe761ca 100644
--- a/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java
+++ b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8150465
  * @summary Unsafe methods to produce uninitialized arrays
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main/othervm -ea -Diters=200   -Xint
  *      compiler.intrinsics.unsafe.AllocateUninitializedArray
diff --git a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java
index eed16e7..f08a3ab 100644
--- a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java
+++ b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8136473
  * @summary Mismatched stores on same slice possible with Unsafe.Put*Unaligned methods
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation
  *      compiler.intrinsics.unsafe.TestUnsafeUnalignedMismatchedAccesses
diff --git a/hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java b/hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java
index faa5a0b..f02308e 100644
--- a/hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java
+++ b/hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 6653795
  * @summary C2 intrinsic for Unsafe.getAddress performs pointer sign extension on 32-bit systems
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main compiler.intrinsics.unsafe.UnsafeGetAddressTest
  */
diff --git a/hotspot/test/compiler/intrinsics/unsafe/UnsafeTwoCASLong.java b/hotspot/test/compiler/intrinsics/unsafe/UnsafeTwoCASLong.java
index 30b604c..8f65f1d 100644
--- a/hotspot/test/compiler/intrinsics/unsafe/UnsafeTwoCASLong.java
+++ b/hotspot/test/compiler/intrinsics/unsafe/UnsafeTwoCASLong.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8143930
  * @summary C1 LinearScan asserts when compiling two back-to-back CompareAndSwapLongs
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run testng/othervm -Diters=200000 -XX:TieredStopAtLevel=1
  *      compiler.intrinsics.unsafe.UnsafeTwoCASLong
diff --git a/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java b/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java
index a8d142e..e923258 100644
--- a/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java
+++ b/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java
@@ -30,6 +30,7 @@
  *          java.compiler
  *          java.instrument
  *          java.management
+ *          jdk.attach
  *
  * @run main/othervm compiler.jsr292.RedefineMethodUsedByMultipleMethodHandles
  */
@@ -42,7 +43,6 @@
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
 
-import javax.tools.ToolProvider;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -132,7 +132,7 @@
         int p = vmName.indexOf('@');
         assert p != -1 : "VM name not in <pid>@<host> format: " + vmName;
         String pid = vmName.substring(0, p);
-        ClassLoader cl = ToolProvider.getSystemToolClassLoader();
+        ClassLoader cl = ClassLoader.getSystemClassLoader();
         Class<?> c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
         Method attach = c.getDeclaredMethod("attach", String.class);
         Method loadAgent = c.getDeclaredMethod("loadAgent", String.class);
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
index 24a60d4..2349b9e 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java
@@ -27,8 +27,8 @@
  * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
  * @library / /test/lib
  * @library ../common/patches
- * @modules java.base/jdk.internal.misc
- * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @modules java.base/jdk.internal.misc:+open
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot:+open
  *
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
  *        jdk.vm.ci/jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java
index d8f256f..8f46daa 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java
@@ -27,10 +27,10 @@
  * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
  * @library / /test/lib
  * @library ../common/patches
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @modules java.base/jdk.internal.org.objectweb.asm
  *          java.base/jdk.internal.org.objectweb.asm.tree
- *          jdk.vm.ci/jdk.vm.ci.hotspot
+ * @modules         jdk.vm.ci/jdk.vm.ci.hotspot:+open
  *          jdk.vm.ci/jdk.vm.ci.code
  *          jdk.vm.ci/jdk.vm.ci.meta
  * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java
index c6b63be..0c4e466 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java
@@ -26,8 +26,8 @@
  * @bug 8136421
  * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
  * @library /test/lib /
- * @modules java.base/jdk.internal.misc
- * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @modules java.base/jdk.internal.misc:open
+ * @modules jdk.vm.ci/jdk.vm.ci.hotspot:open
  *          jdk.vm.ci/jdk.vm.ci.runtime
  * @run main/othervm -XX:+UnlockExperimentalVMOptions
  *      -Dcompiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive=true
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java
index 601b192..a7d2cdd 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MethodHandleAccessProviderTest.java
@@ -27,9 +27,10 @@
  * @bug 8161068
  * @requires (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "aarch64")
  * @library /test/lib /compiler/jvmci/jdk.vm.ci.hotspot.test/src
+ * @modules java.base/java.lang.invoke:+open
  * @modules jdk.vm.ci/jdk.vm.ci.meta
  *          jdk.vm.ci/jdk.vm.ci.runtime
- *          jdk.vm.ci/jdk.vm.ci.hotspot
+ * @modules         jdk.vm.ci/jdk.vm.ci.hotspot:+open
  * @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *      jdk.vm.ci.hotspot.test.MethodHandleAccessProviderTest
  */
diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java
index f56aa75..f859ddf 100644
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java
@@ -27,6 +27,7 @@
  * @library ../../../../../
  * @modules jdk.vm.ci/jdk.vm.ci.meta
  *          jdk.vm.ci/jdk.vm.ci.runtime
+ *          jdk.attach
  *          java.base/jdk.internal.misc
  * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.RedefineClassTest
  */
@@ -37,7 +38,6 @@
 import org.junit.Assert;
 import org.junit.Test;
 
-import javax.tools.ToolProvider;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -137,7 +137,7 @@
         int p = vmName.indexOf('@');
         assumeTrue(p != -1);
         String pid = vmName.substring(0, p);
-        ClassLoader cl = ToolProvider.getSystemToolClassLoader();
+        ClassLoader cl = ClassLoader.getSystemClassLoader();
         Class<?> c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
         Method attach = c.getDeclaredMethod("attach", String.class);
         Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class);
diff --git a/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java b/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java
index 232134d..75adaa3 100644
--- a/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java
+++ b/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java
@@ -26,7 +26,7 @@
  * @bug 8073480
  * @summary explicit range checks should be recognized by C2
  * @library /test/lib /
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
diff --git a/hotspot/test/compiler/runtime/Test8010927.java b/hotspot/test/compiler/runtime/Test8010927.java
index ba50aeb..32b6203 100644
--- a/hotspot/test/compiler/runtime/Test8010927.java
+++ b/hotspot/test/compiler/runtime/Test8010927.java
@@ -26,7 +26,7 @@
  * @bug 8010927
  * @summary Kitchensink crashed with SIGSEGV, Problematic frame: v ~StubRoutines::checkcast_arraycopy
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
diff --git a/hotspot/test/compiler/unsafe/GetUnsafeObjectG1PreBarrier.java b/hotspot/test/compiler/unsafe/GetUnsafeObjectG1PreBarrier.java
index be07553..d68cfca 100644
--- a/hotspot/test/compiler/unsafe/GetUnsafeObjectG1PreBarrier.java
+++ b/hotspot/test/compiler/unsafe/GetUnsafeObjectG1PreBarrier.java
@@ -26,7 +26,7 @@
  * @bug 8016474
  * @summary The bug only happens with C1 and G1 using a different ObjectAlignmentInBytes than KlassAlignmentInBytes (which is 8)
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=32
  *                   compiler.unsafe.GetUnsafeObjectG1PreBarrier
  */
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java
index e98e8b4..50e505b 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestBoolean.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for boolean
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestBoolean
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestBoolean
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestBoolean
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java
index 7828244..e35e590 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestByte.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for byte
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestByte
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java
index c774f6b..0bb36c8 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestChar.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for char
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestChar
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestChar
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestChar
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java
index 8a366bf..48a98c6 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestDouble.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for double
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestDouble
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestDouble
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestDouble
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java
index 03df5ea..2a91a7c 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestFloat.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for float
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestFloat
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestFloat
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestFloat
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java
index 61498e6..b55e367 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestInt.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for int
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestInt
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestInt
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestInt
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java
index 3a07e8e..fc78b37 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestLong.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for long
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestLong
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestLong
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestLong
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java
index 1c5c2d0..039b472 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestObject.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for Object
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestObject
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestObject
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestObject
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java
index 30deaa8..f854979 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeAccessTestShort.java
@@ -26,7 +26,7 @@
  * @bug 8143628
  * @summary Test unsafe access for short
  *
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  * @run testng/othervm -Diters=100   -Xint                   compiler.unsafe.JdkInternalMiscUnsafeAccessTestShort
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 compiler.unsafe.JdkInternalMiscUnsafeAccessTestShort
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  compiler.unsafe.JdkInternalMiscUnsafeAccessTestShort
diff --git a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeUnalignedAccess.java b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeUnalignedAccess.java
index f5b7681..53ccfd7 100644
--- a/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeUnalignedAccess.java
+++ b/hotspot/test/compiler/unsafe/JdkInternalMiscUnsafeUnalignedAccess.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8158260
  * @summary Test unaligned Unsafe accesses
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main/othervm -Diters=20000 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation
  *      compiler.unsafe.JdkInternalMiscUnsafeUnalignedAccess
diff --git a/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
index fde5d53..70c04b5 100644
--- a/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
+++ b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8077504
  * @summary Unsafe load can loose control dependency and cause crash
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:+open
  *
  * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
  *                   compiler.unsafe.TestUnsafeLoadControl
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java b/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java
index aa5192d..8e30385 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationAgeThreshold.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java b/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java
index be88c99..3f21d68 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationFullGC.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationInterned.java b/hotspot/test/gc/g1/TestStringDeduplicationInterned.java
index 48f4b59..c5b82e2 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationInterned.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationInterned.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java b/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java
index bb47eb5..aa321a4 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationPrintOptions.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java b/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java
index 7c52c36..3c2c44e 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTableRehash.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java b/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java
index 2a72f40..8dd2b32 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTableResize.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationTools.java b/hotspot/test/gc/g1/TestStringDeduplicationTools.java
index b476031..f07240e 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationTools.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationTools.java
@@ -190,6 +190,7 @@
             "-Xmx" + Xmx + "m",
             "-XX:+UseG1GC",
             "-XX:+UnlockDiagnosticVMOptions",
+            "--add-opens=java.base/java.lang=ALL-UNNAMED",
             "-XX:+VerifyAfterGC" // Always verify after GC
         };
 
diff --git a/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java b/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java
index 4cbc744..71bb53d 100644
--- a/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java
+++ b/hotspot/test/gc/g1/TestStringDeduplicationYoungGC.java
@@ -28,7 +28,8 @@
  * @key gc
  * @requires vm.gc.G1
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  *          java.management
  */
 
diff --git a/hotspot/test/gc/stress/gcbasher/TestGCBasher.java b/hotspot/test/gc/stress/gcbasher/TestGCBasher.java
index 1229f01..bda2aa7 100644
--- a/hotspot/test/gc/stress/gcbasher/TestGCBasher.java
+++ b/hotspot/test/gc/stress/gcbasher/TestGCBasher.java
@@ -38,7 +38,8 @@
         FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
         Stream<Path> s = Files.walk(fs.getPath("/"));
         for (Path p : (Iterable<Path>)s::iterator) {
-            if (p.toString().endsWith(".class")) {
+            if (p.toString().endsWith(".class") &&
+                !p.getFileName().toString().equals("module-info.class")) {
                 byte[] data = Files.readAllBytes(p);
                 Decompiler d = new Decompiler(data);
                 ClassInfo ci = d.getClassInfo();
diff --git a/hotspot/test/runtime/LocalLong/LocalLongTest.java b/hotspot/test/runtime/LocalLong/LocalLongTest.java
index 2c6d8bf..718f0c4 100644
--- a/hotspot/test/runtime/LocalLong/LocalLongTest.java
+++ b/hotspot/test/runtime/LocalLong/LocalLongTest.java
@@ -39,6 +39,10 @@
     public static void main(String... args) throws Exception {
         if (Platform.is64bit()) {
             ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xint",
+                                                                      "--add-opens",
+                                                                      "java.base/java.lang=ALL-UNNAMED",
+                                                                      "--add-opens",
+                                                                      "java.base/java.lang.invoke=ALL-UNNAMED",
                                                                       "LocalLongHelper");
             OutputAnalyzer o = new OutputAnalyzer(pb.start());
             o.shouldHaveExitValue(0);
diff --git a/hotspot/test/runtime/Throwable/StackTraceLogging.java b/hotspot/test/runtime/Throwable/StackTraceLogging.java
index c9aa912..c86da3a 100644
--- a/hotspot/test/runtime/Throwable/StackTraceLogging.java
+++ b/hotspot/test/runtime/Throwable/StackTraceLogging.java
@@ -52,6 +52,8 @@
     public static void main(String[] args) throws Exception {
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:stacktrace=info",
                                                                   "-XX:MaxJavaStackTraceDepth=1024",
+                                                                  "--add-opens",
+                                                                  "java.base/java.lang=ALL-UNNAMED",
                                                                   "TestThrowable");
         analyzeOutputOn(pb);
     }
diff --git a/hotspot/test/runtime/Throwable/TestThrowable.java b/hotspot/test/runtime/Throwable/TestThrowable.java
index fca76e1..34e4bd1 100644
--- a/hotspot/test/runtime/Throwable/TestThrowable.java
+++ b/hotspot/test/runtime/Throwable/TestThrowable.java
@@ -25,7 +25,8 @@
  * @test
  * @bug 8150778
  * @summary Test exception depths, and code to get stack traces
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  * @library /test/lib
  * @run main/othervm -XX:MaxJavaStackTraceDepth=1024 TestThrowable
  */
diff --git a/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java
index e3eecb4..a242d3a 100644
--- a/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java
+++ b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java
@@ -25,7 +25,8 @@
  * @test
  * @bug 8033735
  * @summary check backtrace field introspection
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  * @run main ThrowableIntrospectionSegfault
  */
 
diff --git a/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java
index fb87f8f..d3f3ca7 100644
--- a/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java
+++ b/hotspot/test/runtime/getSysPackage/GetSysPkgTest.java
@@ -100,7 +100,7 @@
             ClassFileInstaller.writeClassToDisk("GetSysPkg_package/GetSysClass", klassbuf);
 
             ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:bl_dir",
-                "--add-exports=java.base/jdk.internal.loader=ALL-UNNAMED", "-cp", "." + File.pathSeparator +
+                "--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED", "-cp", "." + File.pathSeparator +
                 System.getProperty("test.classes"), "GetSysPkgTest", "do_tests");
             OutputAnalyzer output = new OutputAnalyzer(pb.start());
             output.shouldHaveExitValue(0);
diff --git a/hotspot/test/runtime/modules/AccessCheck/CheckRead.java b/hotspot/test/runtime/modules/AccessCheck/CheckRead.java
index 986fd09..6143f0b 100644
--- a/hotspot/test/runtime/modules/AccessCheck/CheckRead.java
+++ b/hotspot/test/runtime/modules/AccessCheck/CheckRead.java
@@ -69,7 +69,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m3")
                         .exports("p1")
@@ -80,9 +80,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Define module:     m3
@@ -90,10 +90,10 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .requires("m2")
-                        .conceals("p3")
+                        .contains("p3")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java
index e084f73..b0b64a4 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_CheckRead.java
@@ -69,7 +69,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m3")
                         .exports("p1")
@@ -80,9 +80,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Define module:     m3
@@ -90,10 +90,10 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .requires("m2")
-                        .conceals("p3")
+                        .contains("p3")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java
index edbca75..b7088553 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java
@@ -70,7 +70,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .requires("m3")
@@ -82,9 +82,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported to m3
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m3")
+                        .exports("p2", Set.of("m3"))
                         .build();
 
         // Define module:     m3
@@ -92,10 +92,10 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .requires("m2")
-                        .conceals("p3")
+                        .contains("p3")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java
index 3209810..8ca888b 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java
@@ -68,7 +68,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported to unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -79,9 +79,9 @@
         // Packages:          p2
         // Packages exported: package p2 is exported to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java
index c8d156e..e38d541 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java
@@ -69,7 +69,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -80,7 +80,7 @@
         // Packages:          p2
         // Packages exported: package p2 is exported to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
                         .exports("p2")
                         .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java
index afc3ec8..0cc88f7 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java
@@ -68,7 +68,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -79,9 +79,9 @@
         // Packages:          p2
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .conceals("p2")
+                        .contains("p2")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java
index 5f88ede..2a5c723 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_Umod.java
@@ -80,7 +80,7 @@
      // Packages:          p1
      // Packages exported: p1 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p1")
                      .build();
@@ -129,7 +129,7 @@
      // Packages:          p1
      // Packages exported: p1 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p1")
                      .build();
@@ -178,7 +178,7 @@
      // Packages:          p1
      // Packages exported: p1 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p1")
                      .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java b/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java
index b7bb370..b8420c2 100644
--- a/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java
+++ b/hotspot/test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java
@@ -75,7 +75,7 @@
      // Packages:          p3
      // Packages exported: p3 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p3")
                      .build();
@@ -124,7 +124,7 @@
      // Packages:          p3
      // Packages exported: p3 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p3")
                      .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java
index d1c4b20..330d723 100644
--- a/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java
+++ b/hotspot/test/runtime/modules/AccessCheck/ExpQualOther.java
@@ -70,7 +70,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .requires("m3")
@@ -82,9 +82,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported to m3
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m3")
+                        .exports("p2", Set.of("m3"))
                         .build();
 
         // Define module:     m3
@@ -92,10 +92,10 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .requires("m2")
-                        .conceals("p3")
+                        .contains("p3")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java b/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java
index 035008c..31de457 100644
--- a/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java
+++ b/hotspot/test/runtime/modules/AccessCheck/ExpQualToM1.java
@@ -58,7 +58,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -69,9 +69,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported qualifiedly to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java
index 2c321ce..03a3770 100644
--- a/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java
+++ b/hotspot/test/runtime/modules/AccessCheck/ExpUnqual.java
@@ -58,7 +58,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -69,7 +69,7 @@
         // Packages:          p2
         // Packages exported: p2 is exported unqualifiedly
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
                         .exports("p2")
                         .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java
index 7d5fb59..c9a89c8 100644
--- a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java
+++ b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java
@@ -71,7 +71,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -81,9 +81,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported unqualifiedly
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java
index 86e26c5..4f592a1 100644
--- a/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java
+++ b/hotspot/test/runtime/modules/AccessCheck/PkgNotExp.java
@@ -68,7 +68,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -79,9 +79,9 @@
         // Packages:          p2
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .conceals("p2")
+                        .contains("p2")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod.java b/hotspot/test/runtime/modules/AccessCheck/Umod.java
index e8d0a04..255950c 100644
--- a/hotspot/test/runtime/modules/AccessCheck/Umod.java
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod.java
@@ -80,7 +80,7 @@
      // Packages:          p1
      // Packages exported: p1 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p1")
                      .build();
@@ -126,7 +126,7 @@
      // Packages:          p1
      // Packages exported: p1 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p1")
                      .build();
@@ -172,7 +172,7 @@
      // Packages:          p1
      // Packages exported: p1 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p1")
                      .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java
index 2a9db0f..5fcc629 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java
@@ -70,7 +70,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -80,9 +80,9 @@
         // Packages:          p2
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java
index c83998d..ade483a 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java
@@ -70,7 +70,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -80,7 +80,7 @@
         // Packages:          p2
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
                         .exports("p2")
                         .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java
index b4d0461..b5ec6c6 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java
@@ -69,7 +69,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -79,9 +79,9 @@
         // Packages:          p2
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .conceals("p2")
+                        .contains("p2")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java b/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java
index 4ad9b24..7cfcdab 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUPkg.java
@@ -75,7 +75,7 @@
      // Packages:          p3
      // Packages exported: p3 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p3")
                      .build();
@@ -121,7 +121,7 @@
      // Packages:          p3
      // Packages exported: p3 is exported unqualifiedly
      ModuleDescriptor descriptor_m1 =
-             new ModuleDescriptor.Builder("m1")
+             ModuleDescriptor.module("m1")
                      .requires("java.base")
                      .exports("p3")
                      .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java
index 3a64481..01ec39a 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java
@@ -70,7 +70,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -80,9 +80,9 @@
         // Packages:          p6
         // Packages exported: p6 exported to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p6", "m1")
+                        .exports("p6", Set.of("m1"))
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java
index b06cf17..68dd377 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java
@@ -69,7 +69,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -79,9 +79,9 @@
         // Packages:          p6
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .conceals("p6")
+                        .contains("p6")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java
index 33f7482..68abe56 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java
@@ -69,7 +69,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .requires("m3")
@@ -80,9 +80,9 @@
         // Packages:          p6
         // Packages exported: p6 is exported to m3
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p6", "m3")
+                        .exports("p6", Set.of("m3"))
                         .build();
 
         // Define module:     m3
@@ -90,7 +90,7 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .build();
 
diff --git a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java
index f3cda29..da69805 100644
--- a/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java
+++ b/hotspot/test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java
@@ -67,7 +67,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -77,9 +77,9 @@
         // Packages:          p6
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .conceals("p6")
+                        .contains("p6")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java
index 74288ef..0f5aaf2 100644
--- a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpQualOther.java
@@ -69,7 +69,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .requires("m3")
@@ -80,9 +80,9 @@
         // Packages:          p2
         // Packages exported: p2 is exported to m3
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m3")
+                        .exports("p2", Set.of("m3"))
                         .build();
 
         // Define module:     m3
@@ -90,7 +90,7 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .build();
 
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java
index dd69c13..db90a08 100644
--- a/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_ExpUnqual.java
@@ -69,7 +69,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -79,7 +79,7 @@
         // Packages:          p2
         // Packages exported: p2 is exported unqualifiedly
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
                         .exports("p2")
                         .build();
diff --git a/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java b/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java
index e15687e..d140cf8 100644
--- a/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java
+++ b/hotspot/test/runtime/modules/AccessCheck/Umod_PkgNotExp.java
@@ -67,7 +67,7 @@
         // Packages:          none
         // Packages exported: none
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .build();
@@ -77,9 +77,9 @@
         // Packages:          p2
         // Packages exported: none
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .conceals("p2")
+                        .contains("p2")
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java b/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java
index 31b0fb5..352a04f 100644
--- a/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java
+++ b/hotspot/test/runtime/modules/IgnoreModulePropertiesTest.java
@@ -72,6 +72,6 @@
         testOption("--add-reads", "xyzz=yyzd", "jdk.module.addreads.0", "WARNING: Unknown module: xyzz");
         testOption("--add-exports", "java.base/xyzz=yyzd", "jdk.module.addexports.0",
                    "WARNING: package xyzz not in java.base");
-        testOption("--patch-module", "=d", "jdk.module.patch.0", "IllegalArgumentException");
+        testOption("--patch-module", "=d", "jdk.module.patch.0", "Missing module name");
     }
 }
diff --git a/hotspot/test/runtime/modules/JVMAddModulePackage.java b/hotspot/test/runtime/modules/JVMAddModulePackage.java
index 502b449..62106f8 100644
--- a/hotspot/test/runtime/modules/JVMAddModulePackage.java
+++ b/hotspot/test/runtime/modules/JVMAddModulePackage.java
@@ -33,6 +33,7 @@
  */
 
 import static jdk.test.lib.Asserts.*;
+import java.sql.Time;
 
 public class JVMAddModulePackage {
 
@@ -123,6 +124,29 @@
             // Expected
         }
 
+        // Add package named "java" to an module defined to a class loader other than the boot or platform loader.
+        try {
+            // module1 is defined to a MyClassLoader class loader.
+            ModuleHelper.AddModulePackage(module1, "java/foo");
+            throw new RuntimeException("Failed to get the expected IAE");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("prohibited package name")) {
+              throw new RuntimeException("Failed to get expected IAE message for prohibited package name: " + e.getMessage());
+            }
+        }
+
+        // Package "javabar" should be ok
+        ModuleHelper.AddModulePackage(module1, "javabar");
+
+        // Package named "java" defined to the boot class loader, should be ok
+        Object module_javabase = module1.getClass().getModule();
+        ModuleHelper.AddModulePackage(module_javabase, "java/foo");
+
+        // Package named "java" defined to the platform class loader, should be ok
+        // The module java.sql is defined to the platform class loader.
+        java.sql.Time jst = new java.sql.Time(45000); // milliseconds
+        Object module_javasql = jst.getClass().getModule();
+        ModuleHelper.AddModulePackage(module_javasql, "java/foo");
     }
 
     static class MyClassLoader extends ClassLoader { }
diff --git a/hotspot/test/runtime/modules/JVMCanReadModule.java b/hotspot/test/runtime/modules/JVMCanReadModule.java
deleted file mode 100644
index c6707d2..0000000
--- a/hotspot/test/runtime/modules/JVMCanReadModule.java
+++ /dev/null
@@ -1,97 +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
- * @modules java.base/jdk.internal.misc
- * @library /test/lib ..
- * @build sun.hotspot.WhiteBox
- * @compile/module=java.base java/lang/reflect/ModuleHelper.java
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI JVMCanReadModule
- */
-
-import static jdk.test.lib.Asserts.*;
-
-public class JVMCanReadModule {
-
-    public static void main(String args[]) throws Throwable {
-        MyClassLoader asking_cl = new MyClassLoader();
-        MyClassLoader target_cl = new MyClassLoader();
-        Object asking_module, target_module;
-        boolean result;
-
-        asking_module = ModuleHelper.ModuleObject("asking_module", asking_cl, new String[] { "mypackage" });
-        assertNotNull(asking_module, "Module should not be null");
-        ModuleHelper.DefineModule(asking_module, "9.0", "asking_module/here", new String[] { "mypackage" });
-        target_module = ModuleHelper.ModuleObject("target_module", target_cl, new String[] { "yourpackage" });
-        assertNotNull(target_module, "Module should not be null");
-        ModuleHelper.DefineModule(target_module, "9.0", "target_module/here", new String[] { "yourpackage" });
-
-        // Set up relationship
-        ModuleHelper.AddReadsModule(asking_module, target_module);
-
-        // Null asking_module argument, expect an NPE
-        try {
-            result = ModuleHelper.CanReadModule(null, target_module);
-            throw new RuntimeException("Failed to get the expected NPE");
-        } catch(NullPointerException e) {
-            // Expected
-        }
-
-        // Bad asking_module argument, expect an IAE
-        try {
-            result = ModuleHelper.CanReadModule(asking_cl, target_module);
-            throw new RuntimeException("Failed to get the expected IAE");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
-
-        // Bad target_module argument, expect an IAE
-        try {
-            result = ModuleHelper.CanReadModule(asking_module, asking_cl);
-            throw new RuntimeException("Failed to get the expected IAE");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
-
-        // Verify strict modules can not read the unnamed module
-        result = ModuleHelper.CanReadModule(target_module, null);
-        assertFalse(result, "target_module can not read unnamed module");
-
-        // Verify asking_module can read itself
-        result = ModuleHelper.CanReadModule(asking_module, asking_module);
-        assertTrue(result, "asking_module can read itself");
-
-        // Verify asking_module can read target_module
-        result = ModuleHelper.CanReadModule(asking_module, target_module);
-        assertTrue(result, "asking_module can read target_module");
-
-        // Verify target_module cannot read asking_module
-        result = ModuleHelper.CanReadModule(target_module, asking_module);
-        assertTrue(!result, "target_module cannot read asking_module");
-    }
-
-    static class MyClassLoader extends ClassLoader { }
-}
diff --git a/hotspot/test/runtime/modules/JVMDefineModule.java b/hotspot/test/runtime/modules/JVMDefineModule.java
index f4a838a..bc080e5 100644
--- a/hotspot/test/runtime/modules/JVMDefineModule.java
+++ b/hotspot/test/runtime/modules/JVMDefineModule.java
@@ -33,6 +33,7 @@
  */
 
 import static jdk.test.lib.Asserts.*;
+import java.sql.Time;
 
 public class JVMDefineModule {
 
@@ -238,6 +239,39 @@
             }
         }
 
+        // Package named "java" defined to a class loader other than the boot or platform class loader, expect an IAE
+        m = ModuleHelper.ModuleObject("modulejavapkg1", cl, new String[] { "java/foo" });
+        try {
+            // module m is defined to an instance of MyClassLoader class loader
+            ModuleHelper.DefineModule(m, "9.0", "modulejavapkg1", new String[] { "java/foo" });
+            throw new RuntimeException("Failed to get expected IAE for package java/foo");
+        } catch(IllegalArgumentException e) {
+            if (!e.getMessage().contains("prohibited package name")) {
+              throw new RuntimeException("Failed to get expected IAE message for prohibited package name: " + e.getMessage());
+            }
+        }
+
+        // Package named "javabar" defined to a class loader other than the boot or platform class loader, should be ok
+        m = ModuleHelper.ModuleObject("modulejavapkg2", cl, new String[] { "javabar" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "modulejavapkg2", new String[] { "javabar" });
+
+        // Package named "java" defined to the boot class loader, should be ok
+        //   m's type is a java.lang.Object, module is java.base
+        //   java.base module is defined to the boot loader
+        ClassLoader boot_loader = m.getClass().getClassLoader();
+        m = ModuleHelper.ModuleObject("modulejavapkg3", boot_loader, new String[] { "java/foo" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "modulejavapkg3", new String[] { "java/foo" });
+
+        // Package named "java" defined to the platform class loader, should be ok
+        //   java.sql module defined to the platform class loader.
+        java.sql.Time jst = new java.sql.Time(45 * 1000);
+        ClassLoader platform_loader = jst.getClass().getClassLoader();
+        m = ModuleHelper.ModuleObject("modulejavapkg4", platform_loader, new String[] { "java/foo" });
+        assertNotNull(m, "Module should not be null");
+        ModuleHelper.DefineModule(m, "9.0", "modulejavapkg4", new String[] { "java/foo" });
+
         // module version that is null, should be okay
         m = ModuleHelper.ModuleObject("module8", cl, new String[] { "a_package_8" });
         assertNotNull(m, "Module should not be null");
diff --git a/hotspot/test/runtime/modules/JVMIsExportedToModule.java b/hotspot/test/runtime/modules/JVMIsExportedToModule.java
deleted file mode 100644
index 3f58cb5..0000000
--- a/hotspot/test/runtime/modules/JVMIsExportedToModule.java
+++ /dev/null
@@ -1,124 +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
- * @modules java.base/jdk.internal.misc
- * @library /test/lib ..
- * @build sun.hotspot.WhiteBox
- * @compile/module=java.base java/lang/reflect/ModuleHelper.java
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI JVMIsExportedToModule
- */
-
-import static jdk.test.lib.Asserts.*;
-
-public class JVMIsExportedToModule {
-
-    public static void main(String args[]) throws Throwable {
-        MyClassLoader from_cl = new MyClassLoader();
-        MyClassLoader to_cl = new MyClassLoader();
-        Object from_module, to_module;
-        boolean result;
-
-        from_module = ModuleHelper.ModuleObject("from_module", from_cl, new String[] { "mypackage", "this/package" });
-        assertNotNull(from_module, "Module from_module should not be null");
-        ModuleHelper.DefineModule(from_module, "9.0", "from_module/here", new String[] { "mypackage", "this/package" });
-        to_module = ModuleHelper.ModuleObject("to_module", to_cl, new String[] { "yourpackage", "that/package" });
-        assertNotNull(to_module, "Module to_module should not be null");
-        ModuleHelper.DefineModule(to_module, "9.0", "to_module/here", new String[] { "yourpackage", "that/package" });
-
-        Object unnamed_module = JVMIsExportedToModule.class.getModule();
-        assertNotNull(unnamed_module, "Module unnamed_module should not be null");
-
-        // Null from_module argument, expect an NPE
-        try {
-            result = ModuleHelper.IsExportedToModule(null, "mypackage", to_module);
-            throw new RuntimeException("Failed to get the expected NPE for null from_module");
-        } catch(NullPointerException e) {
-            // Expected
-        }
-
-        // Null to_module argument, expect an NPE
-        try {
-          result = ModuleHelper.IsExportedToModule(from_module, "mypackage", null);
-          throw new RuntimeException("Failed to get expected NPE for null to_module");
-        } catch(NullPointerException e) {
-            // Expected
-        }
-
-        // Null package argument, expect an NPE
-        try {
-            result = ModuleHelper.IsExportedToModule(from_module, null, to_module);
-            throw new RuntimeException("Failed to get the expected NPE for null package");
-        } catch(NullPointerException e) {
-            // Expected
-        }
-
-        // Bad from_module argument, expect an IAE
-        try {
-            result = ModuleHelper.IsExportedToModule(to_cl, "mypackage", to_module);
-            throw new RuntimeException("Failed to get the expected IAE for bad from_module");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
-
-        // Bad to_module argument, expect an IAE
-        try {
-            result = ModuleHelper.IsExportedToModule(from_module, "mypackage", from_cl);
-            throw new RuntimeException("Failed to get the expected IAE");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
-
-        // Check that package is exported to its own module
-        result = ModuleHelper.IsExportedToModule(from_module, "mypackage", from_module);
-        assertTrue(result, "Package is always exported to itself");
-
-        // Package is not in to_module, expect an IAE
-        try {
-            result = ModuleHelper.IsExportedToModule(from_module, "yourpackage", from_cl);
-            throw new RuntimeException("Failed to get the expected IAE for package not in to_module");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
-
-        // Package is accessible when exported to unnamed module
-        ModuleHelper.AddModuleExportsToAll(from_module, "mypackage");
-        result = ModuleHelper.IsExportedToModule(from_module, "mypackage", to_module);
-        assertTrue(result, "Package exported to unnamed module is visible to named module");
-
-        result = ModuleHelper.IsExportedToModule(from_module, "mypackage", unnamed_module);
-        assertTrue(result, "Package exported to unnamed module is visible to unnamed module");
-
-        // Package is accessible only to named module when exported to named module
-        ModuleHelper.AddModuleExports(from_module, "this/package", to_module);
-        result = ModuleHelper.IsExportedToModule(from_module, "this/package", to_module);
-        assertTrue(result, "Package exported to named module is visible to named module");
-        result = ModuleHelper.IsExportedToModule(from_module, "this/package", unnamed_module);
-        assertTrue(!result, "Package exported to named module is not visible to unnamed module");
-    }
-
-    static class MyClassLoader extends ClassLoader { }
-}
diff --git a/hotspot/test/runtime/modules/ModuleHelper.java b/hotspot/test/runtime/modules/ModuleHelper.java
index 2761b48..2f0d7f6 100644
--- a/hotspot/test/runtime/modules/ModuleHelper.java
+++ b/hotspot/test/runtime/modules/ModuleHelper.java
@@ -73,17 +73,6 @@
         java.lang.reflect.ModuleHelper.addExportsNoSync((Module)m, pkg, (Module)null);
     }
 
-    public static boolean CanReadModule(Object from, Object to) throws Throwable {
-        WhiteBox wb = WhiteBox.getWhiteBox();
-        return wb.CanReadModule(from, to);
-    }
-
-    public static boolean IsExportedToModule(Object from, String pkg,
-                                             Object to) throws Throwable {
-        WhiteBox wb = WhiteBox.getWhiteBox();
-        return wb.IsExportedToModule(from, pkg, to);
-    }
-
     public static Module ModuleObject(String name, ClassLoader loader, String[] pkgs) throws Throwable {
         Set<String> pkg_set = new HashSet<>();
         if (pkgs != null) {
@@ -95,7 +84,7 @@
         }
 
         ModuleDescriptor descriptor =
-            new ModuleDescriptor.Builder(name).conceals(pkg_set).build();
+            ModuleDescriptor.module(name).contains(pkg_set).build();
         URI uri = URI.create("module:/" + name);
 
         return java.lang.reflect.ModuleHelper.newModule(loader, descriptor);
diff --git a/hotspot/test/runtime/modules/ModuleStress/ModuleNonBuiltinCLMain.java b/hotspot/test/runtime/modules/ModuleStress/ModuleNonBuiltinCLMain.java
index a8390f0..79e56f2 100644
--- a/hotspot/test/runtime/modules/ModuleStress/ModuleNonBuiltinCLMain.java
+++ b/hotspot/test/runtime/modules/ModuleStress/ModuleNonBuiltinCLMain.java
@@ -57,7 +57,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported to unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -71,7 +71,7 @@
         targets.add("m1");
         targets.add("m3");
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
                         .requires("m3")
                         .exports("p2", targets)
@@ -82,7 +82,7 @@
         // Packages:          p3
         // Packages exported: none
         ModuleDescriptor descriptor_m3 =
-                new ModuleDescriptor.Builder("m3")
+                ModuleDescriptor.module("m3")
                         .requires("java.base")
                         .build();
 
diff --git a/hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java b/hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java
index b14a9a9..cdbc900 100644
--- a/hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java
+++ b/hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java
@@ -55,7 +55,7 @@
         // Packages:          p1
         // Packages exported: p1 is exported to unqualifiedly
         ModuleDescriptor descriptor_m1 =
-                new ModuleDescriptor.Builder("m1")
+                ModuleDescriptor.module("m1")
                         .requires("java.base")
                         .requires("m2")
                         .exports("p1")
@@ -66,9 +66,9 @@
         // Packages:          p2
         // Packages exported: package p2 is exported to m1
         ModuleDescriptor descriptor_m2 =
-                new ModuleDescriptor.Builder("m2")
+                ModuleDescriptor.module("m2")
                         .requires("java.base")
-                        .exports("p2", "m1")
+                        .exports("p2", Set.of("m1"))
                         .build();
 
         // Set up a ModuleFinder containing all modules for this layer.
diff --git a/hotspot/test/runtime/modules/getModuleJNI/GetModule.java b/hotspot/test/runtime/modules/getModuleJNI/GetModule.java
index c9ef495..01d0064 100644
--- a/hotspot/test/runtime/modules/getModuleJNI/GetModule.java
+++ b/hotspot/test/runtime/modules/getModuleJNI/GetModule.java
@@ -35,10 +35,6 @@
     }
 
     static native Object callGetModule(java.lang.Class clazz);
-    static native void callAddModuleReads(java.lang.reflect.Module from_module,
-                                          java.lang.reflect.Module source_module);
-    static native boolean callCanReadModule(java.lang.reflect.Module asking_module,
-                                            java.lang.reflect.Module source_module);
 
     public static void main(String[] args) {
         Module module;
@@ -144,71 +140,6 @@
         } catch(NullPointerException e) {
             // Expected
         }
-
-
-        // Tests for JNI_AddModuleReads() //
-
-        Module javaScriptingModule = javax.script.Bindings.class.getModule();
-        if (javaScriptingModule == null) {
-            throw new RuntimeException("Failed to get java.scripting module");
-        }
-        Module javaLoggingModule = java.util.logging.Level.class.getModule();
-        if (javaLoggingModule == null) {
-            throw new RuntimeException("Failed to get java.logging module");
-        }
-
-        if (callCanReadModule(javaLoggingModule, javaScriptingModule)) {
-            throw new RuntimeException(
-                "Expected FALSE because javaLoggingModule cannot read javaScriptingModule");
-        }
-
-        callAddModuleReads(javaLoggingModule, javaScriptingModule);
-        callAddModuleReads(javaScriptingModule, GetModule.class.getModule()); // unnamed module
-
-        try {
-            callAddModuleReads(null, javaLoggingModule);
-            throw new RuntimeException(
-                "Expected NullPointerException for bad from_module not thrown");
-        } catch(NullPointerException e) {
-            // expected
-        }
-
-        try {
-          callAddModuleReads(javaLoggingModule, null);
-          throw new RuntimeException(
-                "Expected NullPointerException for bad source_module not thrown");
-        } catch(NullPointerException e) {
-            // expected
-        }
-
-
-        // Tests for JNI_CanReadModule() //
-
-        if (!callCanReadModule(javaLoggingModule, javaScriptingModule)) {
-            throw new RuntimeException(
-                "Expected TRUE because javaLoggingModule can read javaScriptingModule");
-        }
-
-        if (callCanReadModule(javaBaseModule, javaScriptingModule)) {
-            throw new RuntimeException(
-                "Expected FALSE because javaBaseModule cannnot read javaScriptingModule");
-        }
-
-        try {
-            callCanReadModule(javaLoggingModule, null);
-            throw new RuntimeException(
-                "Expected NullPointerException for bad sourceModule not thrown");
-        } catch(NullPointerException e) {
-            // expected
-        }
-
-        try {
-            callCanReadModule(null, javaScriptingModule);
-            throw new RuntimeException(
-                "Expected NullPointerException for bad asking_module not thrown");
-        } catch(NullPointerException e) {
-            // expected
-        }
     }
 
     static class MyClassLoader extends ClassLoader { }
diff --git a/hotspot/test/runtime/modules/getModuleJNI/libGetModule.c b/hotspot/test/runtime/modules/getModuleJNI/libGetModule.c
index a7b1b6d..e21424f 100644
--- a/hotspot/test/runtime/modules/getModuleJNI/libGetModule.c
+++ b/hotspot/test/runtime/modules/getModuleJNI/libGetModule.c
@@ -28,15 +28,3 @@
     jobject res = (jobject)((*env)->GetModule(env, clazz));
     return res;
 }
-
-JNIEXPORT void JNICALL
-Java_GetModule_callAddModuleReads(JNIEnv *env, jclass unused, jobject from_module, jobject source_module) {
-    (*env)->AddModuleReads(env, from_module, source_module);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_GetModule_callCanReadModule(JNIEnv *env, jclass unused, jobject asking_module, jobject source_module) {
-   jboolean res = (*env)->CanReadModule(env, asking_module, source_module);
-   return res;
-}
-
diff --git a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java
index 8be22f0..99cc943 100644
--- a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java
+++ b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java
@@ -26,7 +26,8 @@
  * @bug 7162400
  * @key regression
  * @summary Regression test for attach issue where stale pid files in /tmp lead to connection issues
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.misc:open
+ * @modules java.base/java.lang:open
  * @modules jdk.attach/sun.tools.attach
  * @library /test/lib
  * @run main AttachWithStalePidFile
diff --git a/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java b/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java
index 16ae4a1..92a2aa4 100644
--- a/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java
+++ b/hotspot/test/serviceability/jdwp/AllModulesCommandTest.java
@@ -32,7 +32,7 @@
  * @test
  * @summary Tests the modules-related JDWP commands
  * @library /test/lib
- * @ignore 8168478
+ * @ignore 8170541
  * @modules jdk.jdwp.agent
  * @modules java.base/jdk.internal.misc
  * @compile AllModulesCommandTestDebuggee.java
@@ -96,8 +96,7 @@
                 if (modName != null) { // JDWP reports unnamed modules, ignore them
                     jdwpModuleNames.add(modName);
                 }
-                // Assert the JDWP CANREAD and CLASSLOADER commands
-                assertCanRead(modId, modName);
+                // Assert the CLASSLOADER commands
                 assertClassLoader(modId, modName);
             }
 
@@ -134,13 +133,6 @@
         }
     }
 
-    private void assertCanRead(long modId, String modName) throws IOException {
-        // Simple assert for the CANREAD command
-        JdwpCanReadReply reply = new JdwpCanReadCmd(modId, modId).send(channel);
-        assertReply(reply);
-        assertTrue(reply.canRead(), "canRead() reports false for reading from the same module '" + modName + "', moduleId=" + modId);
-    }
-
     private void assertClassLoader(long modId, String modName) throws IOException {
         // Verify that the module classloader id is valid
         JdwpClassLoaderReply reply = new JdwpClassLoaderCmd(modId).send(channel);
diff --git a/hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java b/hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java
deleted file mode 100644
index 81cb5a9..0000000
--- a/hotspot/test/serviceability/jdwp/JdwpCanReadCmd.java
+++ /dev/null
@@ -1,35 +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.
- */
-
-/**
- * The JDWP CANREAD command
- */
-public class JdwpCanReadCmd extends JdwpCmd<JdwpCanReadReply> {
-
-    public JdwpCanReadCmd(long modId, long srcModId) {
-        super(3, 18, JdwpCanReadReply.class, 2 * refLen());
-        putRefId(modId);
-        putRefId(srcModId);
-    }
-
-}
diff --git a/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/MyPackage/AddModuleExportsAndOpensTest.java b/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/MyPackage/AddModuleExportsAndOpensTest.java
new file mode 100644
index 0000000..04446a6
--- /dev/null
+++ b/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/MyPackage/AddModuleExportsAndOpensTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package MyPackage;
+
+/**
+ * @test
+ * @summary Verifies the JVMTI AddModuleExports and AddModuleOpens API
+ * @compile AddModuleExportsAndOpensTest.java
+ * @run main/othervm/native -agentlib:AddModuleExportsAndOpensTest MyPackage.AddModuleExportsAndOpensTest
+ */
+
+import java.io.PrintStream;
+import java.lang.reflect.Module;
+
+public class AddModuleExportsAndOpensTest {
+
+    static {
+        try {
+            System.loadLibrary("AddModuleExportsAndOpensTest");
+        } catch (UnsatisfiedLinkError ule) {
+            System.err.println("Could not load AddModuleExportsAndOpensTest library");
+            System.err.println("java.library.path: "
+                + System.getProperty("java.library.path"));
+            throw ule;
+        }
+    }
+
+    native static int check(Module baseModule, Module thisModule);
+
+    public static void main(String args[]) {
+        Module baseModule = Object.class.getModule();
+        Module thisModule = AddModuleExportsAndOpensTest.class.getClassLoader().getUnnamedModule();
+        int status = check(baseModule, thisModule);
+        if (status != 0) {
+            throw new RuntimeException("Non-zero status returned from the agent: " + status);
+        }
+    }
+}
diff --git a/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/libAddModuleExportsAndOpensTest.c b/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/libAddModuleExportsAndOpensTest.c
new file mode 100644
index 0000000..351dfc4
--- /dev/null
+++ b/hotspot/test/serviceability/jvmti/AddModuleExportsAndOpens/libAddModuleExportsAndOpensTest.c
@@ -0,0 +1,298 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXC_CNAME = "java/lang/Exception";
+static const char* MOD_CNAME = "Ljava/lang/reflect/Module;";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+    return JNI_VERSION_1_8;
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+    jint res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+                                        JVMTI_VERSION_9);
+    if (res != JNI_OK || jvmti == NULL) {
+        printf("    Error: wrong result of a valid call to GetEnv!\n");
+        return JNI_ERR;
+    }
+
+    return JNI_OK;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+    jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+    if (exc_class == NULL) {
+        printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+        return -1;
+    }
+    return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+static
+jclass jlrM(JNIEnv *env) {
+    jclass cls = NULL;
+
+    cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME));
+    if (cls == NULL) {
+        printf("    Error in JNI FindClass: %s\n", MOD_CNAME);
+    }
+    return cls;
+}
+
+jmethodID
+get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) {
+    jmethodID method = NULL;
+
+    method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig);
+    if (method == NULL) {
+        printf("    Error in JNI GetMethodID %s with signature %s", name, sig);
+    }
+    return method;
+}
+
+static
+jboolean is_exported(JNIEnv *env, jobject module, const char* pkg, jboolean open) {
+    static jmethodID mIsExported = NULL;
+    jstring jstr = NULL;
+    jboolean res = JNI_FALSE;
+
+    if (mIsExported == NULL) {
+        const char* sign = "(Ljava/lang/String;)Z";
+        const char* name = open ? "isOpen" : "isExported";
+        mIsExported = get_method(env, jlrM(env), name, sign);
+    }
+    jstr = JNI_ENV_PTR(env)->NewStringUTF(JNI_ENV_ARG(env, pkg));
+    res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module),
+                                              mIsExported, jstr);
+    return res;
+}
+
+static
+jboolean is_exported_to(JNIEnv *env, jobject module, const char* pkg, jobject to_module,
+                        jboolean open) {
+    static jmethodID mIsExportedTo = NULL;
+    jstring jstr = NULL;
+    jboolean res = JNI_FALSE;
+
+    if (mIsExportedTo == NULL) {
+        const char* sign = "(Ljava/lang/String;Ljava/lang/reflect/Module;)Z";
+        const char* name = open ? "isOpen" : "isExported";
+        mIsExportedTo = get_method(env, jlrM(env), name, sign);
+    }
+    jstr = JNI_ENV_PTR(env)->NewStringUTF(JNI_ENV_ARG(env, pkg));
+    res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module),
+                                              mIsExportedTo, jstr, to_module);
+    return res;
+}
+
+static
+jvmtiError add_module_exports(jobject baseModule, const char* pkg, jobject thisModule,
+                              jboolean open) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    if (open) {
+        err = (*jvmti)->AddModuleOpens(jvmti, baseModule, pkg, thisModule);
+    } else {
+        err = (*jvmti)->AddModuleExports(jvmti, baseModule, pkg, thisModule);
+    }
+    return err;
+}
+
+static
+jint check_add_module_exports(JNIEnv *env,
+                              jclass  cls,
+                              jobject baseModule,
+                              jobject thisModule,
+                              jboolean open) {
+    static char strbuf[128] = { '\0' };
+    jvmtiError err = JVMTI_ERROR_NONE;
+    const char* pkg = open ? "jdk.internal.math"
+                           : "jdk.internal.misc";
+    const char* bad_pkg = "my.bad.pkg";
+    const char* jvmti_fn = open ? "AddModuleOpens"
+                                : "AddModuleExports";
+    jboolean exported = JNI_FALSE;
+
+    // Export from NULL module
+    printf("Check #N1:\n");
+    err = add_module_exports(NULL, pkg, thisModule, open);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#N1: jvmtiError from %s: %d\n", jvmti_fn, err);
+        throw_exc(env, "Check #N1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL");
+        return FAILED;
+    }
+
+    // Export NULL package
+    printf("Check #N2:\n");
+    err = add_module_exports(baseModule, NULL, thisModule, open);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#N2: jvmtiError from %s: %d\n", jvmti_fn, err);
+        throw_exc(env, "Check #N2: failed to return JVMTI_ERROR_NULL_POINTER for pkg==NULL");
+        return FAILED;
+    }
+
+    // Export to NULL module
+    printf("Check #N3:\n");
+    err = add_module_exports(baseModule, pkg, NULL, open);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#N3: jvmtiError from %s: %d\n", jvmti_fn, err);
+        throw_exc(env, "Check #N3: failed to return JVMTI_ERROR_NULL_POINTER for to_module==NULL");
+        return FAILED;
+    }
+
+    // Export a bad package
+    printf("Check #I0:\n");
+    err = add_module_exports(baseModule, bad_pkg, thisModule, open);
+    if (err != JVMTI_ERROR_ILLEGAL_ARGUMENT) {
+        printf("#I0: jvmtiError from %s: %d\n", jvmti_fn, err);
+        throw_exc(env, "Check #I0: did not get expected JVMTI_ERROR_ILLEGAL_ARGUMENT for invalid package");
+        return FAILED;
+    }
+
+    // Export from invalid module (cls)
+    printf("Check #I1:\n");
+    err = add_module_exports((jobject)cls, pkg, thisModule, open);
+    if (err != JVMTI_ERROR_INVALID_MODULE) {
+        printf("#I1: jvmtiError from %s: %d\n", jvmti_fn, err);
+        throw_exc(env, "Check #I1: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid module");
+        return FAILED;
+    }
+
+    // Export to invalid module (cls)
+    printf("Check #I2:\n");
+    err = add_module_exports(baseModule, pkg, (jobject)cls, open);
+    if (err != JVMTI_ERROR_INVALID_MODULE) {
+        printf("#I2: jvmtiError from %s: %d\n", jvmti_fn, err);
+        throw_exc(env, "Check #I2: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid to_module");
+        return FAILED;
+    }
+
+    // Check the pkg is not exported from baseModule to thisModule
+    printf("Check #C0:\n");
+    exported = is_exported_to(env, baseModule, pkg, thisModule, open);
+    if (exported != JNI_FALSE) {
+        sprintf(strbuf, "Check #C0: unexpected export of %s from base to this", pkg);
+        throw_exc(env, strbuf);
+        return FAILED;
+    }
+
+    // Add export of the pkg from baseModule to thisModule
+    printf("Check #C1:\n");
+    err = add_module_exports(baseModule, pkg, thisModule, open);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("#C1: jvmtiError from %s: %d\n", jvmti_fn, err);
+        sprintf(strbuf, "Check #C1: error in add export of %s from base to this", pkg);
+        throw_exc(env, strbuf);
+        return FAILED;
+    }
+
+    // Check the pkg is exported from baseModule to thisModule
+    printf("Check #C2:\n");
+    exported = is_exported_to(env, baseModule, pkg, thisModule, open);
+    if (exported == JNI_FALSE) {
+        sprintf(strbuf, "Check #C2: failed to export %s from base to this", pkg);
+        throw_exc(env, strbuf);
+        return FAILED;
+    }
+
+    // Check the pkg is not exported to all modules
+    printf("Check #C3:\n");
+    exported = is_exported(env, baseModule, pkg, open);
+    if (exported != JNI_FALSE) {
+        sprintf(strbuf, "Check #C3: unexpected export of %s from base to all modules", pkg);
+        throw_exc(env, strbuf);
+        return FAILED;
+    }
+    return PASSED;
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_AddModuleExportsAndOpensTest_check(JNIEnv *env,
+                                                  jclass cls,
+                                                  jobject baseModule,
+                                                  jobject thisModule) {
+    if (jvmti == NULL) {
+        throw_exc(env, "JVMTI client was not properly loaded!\n");
+        return FAILED;
+    }
+
+    printf("\n*** Checks for JVMTI AddModuleExports ***\n\n");
+    result = check_add_module_exports(env, cls, baseModule, thisModule, JNI_FALSE);
+    if (result != PASSED) {
+        return result;
+    }
+
+    printf("\n*** Checks for JVMTI AddModuleOpens ***\n\n");
+    result = check_add_module_exports(env, cls, baseModule, thisModule, JNI_TRUE);
+    if (result != PASSED) {
+        return result;
+    }
+    return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hotspot/test/serviceability/jvmti/AddModuleReads/MyPackage/AddModuleReadsTest.java b/hotspot/test/serviceability/jvmti/AddModuleReads/MyPackage/AddModuleReadsTest.java
new file mode 100644
index 0000000..940172a
--- /dev/null
+++ b/hotspot/test/serviceability/jvmti/AddModuleReads/MyPackage/AddModuleReadsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package MyPackage;
+
+/**
+ * @test
+ * @summary Verifies the JVMTI AddModuleReads API
+ * @compile AddModuleReadsTest.java
+ * @run main/othervm/native -agentlib:AddModuleReadsTest MyPackage.AddModuleReadsTest
+ */
+
+import java.io.PrintStream;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Module;
+
+public class AddModuleReadsTest {
+
+    static {
+        try {
+            System.loadLibrary("AddModuleReadsTest");
+        } catch (UnsatisfiedLinkError ule) {
+            System.err.println("Could not load AddModuleReadsTest library");
+            System.err.println("java.library.path: "
+                + System.getProperty("java.library.path"));
+            throw ule;
+        }
+    }
+
+    native static int check(Module unnamed, Module base, Module instrument);
+
+    public static void main(String args[]) {
+        Module unnamed = AddModuleReadsTest.class.getClassLoader().getUnnamedModule();
+        Module base = Object.class.getModule();
+        Module instrument = Instrumentation.class.getModule();
+        int status = check(unnamed, base, instrument);
+        if (status != 0) {
+            throw new RuntimeException("Non-zero status returned from the agent: " + status);
+        }
+    }
+}
diff --git a/hotspot/test/serviceability/jvmti/AddModuleReads/libAddModuleReadsTest.c b/hotspot/test/serviceability/jvmti/AddModuleReads/libAddModuleReadsTest.c
new file mode 100644
index 0000000..8d33914
--- /dev/null
+++ b/hotspot/test/serviceability/jvmti/AddModuleReads/libAddModuleReadsTest.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXC_CNAME = "java/lang/Exception";
+static const char* MOD_CNAME = "Ljava/lang/reflect/Module;";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+    return JNI_VERSION_1_8;
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+    jint res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+                                        JVMTI_VERSION_9);
+    if (res != JNI_OK || jvmti == NULL) {
+        printf("    Error: wrong result of a valid call to GetEnv!\n");
+        return JNI_ERR;
+    }
+    return JNI_OK;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+    jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+    if (exc_class == NULL) {
+        printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+        return -1;
+    }
+    return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+static
+jclass jlrM(JNIEnv *env) {
+    jclass cls = NULL;
+
+    cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME));
+    if (cls == NULL) {
+        printf("    Error in JNI FindClass: %s\n", MOD_CNAME);
+    }
+    return cls;
+}
+
+jmethodID
+get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) {
+    jmethodID method = NULL;
+
+    method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig);
+    if (method == NULL) {
+        printf("    Error in JNI GetMethodID %s with signature %s", name, sig);
+    }
+    return method;
+}
+
+static
+jboolean can_module_read(JNIEnv *env, jobject module, jobject to_module) {
+    static jmethodID mCanRead = NULL;
+    jboolean res = JNI_FALSE;
+
+    if (mCanRead == NULL) {
+        const char* sign = "(Ljava/lang/reflect/Module;)Z";
+        mCanRead = get_method(env, jlrM(env), "canRead", sign);
+    }
+    res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module),
+                                              mCanRead, to_module);
+    return res;
+}
+
+static
+jint check_add_module_reads(JNIEnv *env,
+                            jclass  cls,
+                            jobject unnamedModule,
+                            jobject baseModule,
+                            jobject instrModule) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    jboolean can = JNI_FALSE;
+
+    // Add an invalid read edge from NULL module
+    printf("Check #N1:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, NULL, baseModule);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#N1: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #N1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL");
+        return FAILED;
+    }
+
+    // Add an invalid read edge to NULL module
+    printf("Check #N2:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, baseModule, NULL);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#N2: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #N2: failed to return JVMTI_ERROR_NULL_POINTER for to_module==NULL");
+        return FAILED;
+    }
+
+    // Add an invalid read edge from invalid module (cls)
+    printf("Check #I1:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, cls, baseModule);
+    if (err != JVMTI_ERROR_INVALID_MODULE) {
+        printf("#I1: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #I1: failed to return JVMTI_ERROR_INVALID_MODULE for module==cls");
+        return FAILED;
+    }
+
+    // Add an invalid read edge to invalid module (cls)
+    printf("Check #I2:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, baseModule, cls);
+    if (err != JVMTI_ERROR_INVALID_MODULE) {
+        printf("#I2: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #I2: failed to return JVMTI_ERROR_INVALID_MODULE for to_module==cls");
+        return FAILED;
+    }
+
+    // Check the edge baseModule->instrModule is absent
+    printf("Check #C0:\n");
+    can = can_module_read(env, baseModule, instrModule);
+    if (can != JNI_FALSE) {
+        throw_exc(env, "Check #C0: read edge from base to instr is unexpected");
+        return FAILED;
+    }
+
+    // Add read edge baseModule->instrModule
+    printf("Check #C1:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, baseModule, instrModule);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("#C1: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #C1: error in add reads from base to instr");
+        return FAILED;
+    }
+
+    // Check the read edge baseModule->instrModule is present now
+    printf("Check #C2:\n");
+    can = can_module_read(env, baseModule, instrModule);
+    if (can == JNI_FALSE) {
+        throw_exc(env, "Check #C2: failed to add reads from base to instr");
+        return FAILED;
+    }
+
+    // Check the read edge baseModule->unnamedModule is absent
+    printf("Check #C3:\n");
+    can = can_module_read(env, baseModule, unnamedModule);
+    if (can != JNI_FALSE) {
+        throw_exc(env, "Check #C3: got unexpected read edge from base to unnamed");
+        return FAILED;
+    }
+
+    // Add read edge baseModule->unnamedModule
+    printf("Check #C4:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, baseModule, unnamedModule);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("#C4: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #C4: failed to ignore adding read edge from base to unnamed");
+        return FAILED;
+    }
+
+    // Check the read edge baseModule->unnamedModule is present now
+    printf("Check #C5:\n");
+    can = can_module_read(env, baseModule, unnamedModule);
+    if (can == JNI_FALSE) {
+        throw_exc(env, "Check #C5: did not get expected read edge from base to unnamed");
+        return FAILED;
+    }
+
+    // Check the read edge unnamedModule->instrModule is absent
+    printf("Check #C6:\n");
+    can = can_module_read(env, unnamedModule, instrModule);
+    if (can == JNI_FALSE) {
+        throw_exc(env, "Check #C6: did not get expected read edge from unnamed to instr");
+        return FAILED;
+    }
+
+    // Add read edge unnamedModule->instrModule
+    printf("Check #C7:\n");
+    err = (*jvmti)->AddModuleReads(jvmti, unnamedModule, instrModule);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("#C7: jvmtiError from AddModuleReads: %d\n", err);
+        throw_exc(env, "Check #C7: failed to ignore adding read edge from unnamed to instr");
+        return FAILED;
+    }
+    return PASSED;
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_AddModuleReadsTest_check(JNIEnv *env,
+                                        jclass cls,
+                                        jobject unnamedModule,
+                                        jobject baseModule,
+                                        jobject instrModule) {
+    if (jvmti == NULL) {
+        throw_exc(env, "JVMTI client was not properly loaded!\n");
+        return FAILED;
+    }
+
+    printf("\n*** Checks for JVMTI AddModuleReads ***\n\n");
+    result = check_add_module_reads(env, cls, unnamedModule, baseModule, instrModule);
+    if (result != PASSED) {
+        return result;
+    }
+    return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/AddModuleUsesAndProvidesTest.java b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/AddModuleUsesAndProvidesTest.java
new file mode 100644
index 0000000..e6d9d57
--- /dev/null
+++ b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/AddModuleUsesAndProvidesTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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 MyPackage;
+
+/**
+ * @test
+ * @summary Basic test for JVMTI AddModuleUses and AddModuleProvides
+ * @build java.base/java.lang.TestProvider
+ *        java.base/jdk.internal.test.TestProviderImpl
+ * @compile AddModuleUsesAndProvidesTest.java
+ * @run main/othervm/native -agentlib:AddModuleUsesAndProvidesTest MyPackage.AddModuleUsesAndProvidesTest
+ */
+
+import java.io.PrintStream;
+import java.lang.TestProvider;
+import java.lang.reflect.Module;
+
+public class AddModuleUsesAndProvidesTest {
+
+    static {
+        try {
+            System.loadLibrary("AddModuleUsesAndProvidesTest");
+        } catch (UnsatisfiedLinkError ule) {
+            System.err.println("Could not load AddModuleUsesAndProvidesTest library");
+            System.err.println("java.library.path: "
+                + System.getProperty("java.library.path"));
+            throw ule;
+        }
+    }
+
+    native static int checkUses(Module baseModule, Class<?> service);
+    native static int checkProvides(Module baseModule, Class<?> service, Class<?> serviceImpl);
+
+    public static void main(String args[]) throws Exception {
+        Module baseModule = Object.class.getModule();
+        Class<?> service = TestProvider.class;
+        Class<?> serviceImpl = Class.forName("jdk.internal.test.TestProviderImpl");
+
+        System.out.println("\n*** Checks for JVMTI AddModuleUses ***\n");
+
+        int status = checkUses(baseModule, service);
+        if (status != 0) {
+            throw new RuntimeException("Non-zero status returned from the agent: " + status);
+        }
+
+        System.out.println("\n*** Checks for JVMTI AddModuleProvides ***\n");
+
+        System.out.println("Check #PC1:");
+        if (TestProvider.providers().iterator().hasNext()) {
+            throw new RuntimeException("Check #PC1: Unexpectedly service is provided");
+        }
+
+        status = checkProvides(baseModule, service, serviceImpl);
+        if (status != 0) {
+            throw new RuntimeException("Non-zero status returned from the agent: " + status);
+        }
+
+        System.out.println("Check #PC3:");
+        if (!TestProvider.providers().iterator().hasNext()) {
+            throw new RuntimeException("Check #PC3: Unexpectedly service is not provided");
+        }
+    }
+}
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/java.base/java/lang/TestProvider.java
similarity index 83%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/java.base/java/lang/TestProvider.java
index 242f168..696d2e9 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/java.base/java/lang/TestProvider.java
@@ -21,5 +21,12 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package java.lang;
+
+import java.util.ServiceLoader;
+
+public interface TestProvider {
+    public static Iterable<TestProvider> providers() {
+        return ServiceLoader.load(TestProvider.class);
+    }
+}
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/java.base/jdk/internal/test/TestProviderImpl.java
similarity index 86%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/java.base/jdk/internal/test/TestProviderImpl.java
index 242f168..b87f43c 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/MyPackage/java.base/jdk/internal/test/TestProviderImpl.java
@@ -21,5 +21,11 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package jdk.internal.test;
+
+import java.lang.TestProvider;
+
+public class TestProviderImpl implements TestProvider {
+    public TestProviderImpl() { }
+}
+
diff --git a/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/libAddModuleUsesAndProvidesTest.c b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/libAddModuleUsesAndProvidesTest.c
new file mode 100644
index 0000000..0d993f6
--- /dev/null
+++ b/hotspot/test/serviceability/jvmti/AddModuleUsesAndProvides/libAddModuleUsesAndProvidesTest.c
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXC_CNAME = "java/lang/Exception";
+static const char* MOD_CNAME = "Ljava/lang/reflect/Module;";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+    return JNI_VERSION_1_8;
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+    jint res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+                                        JVMTI_VERSION_9);
+    if (res != JNI_OK || jvmti == NULL) {
+        printf("    Error: wrong result of a valid call to GetEnv!\n");
+        return JNI_ERR;
+    }
+
+    return JNI_OK;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+    jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+    if (exc_class == NULL) {
+        printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+        return -1;
+    }
+    return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+static
+jclass jlrM(JNIEnv *env) {
+    jclass cls = NULL;
+
+    cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, MOD_CNAME));
+    if (cls == NULL) {
+        printf("    Error in JNI FindClass: %s\n", MOD_CNAME);
+    }
+    return cls;
+}
+
+jmethodID
+get_method(JNIEnv *env, jclass clazz, const char * name, const char *sig) {
+    jmethodID method = NULL;
+
+    method = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG(env, clazz), name, sig);
+    if (method == NULL) {
+        printf("    Error in JNI GetMethodID %s with signature %s", name, sig);
+    }
+    return method;
+}
+
+static
+jboolean can_use_service(JNIEnv *env, jobject module, jclass service) {
+    static jmethodID mCanUse = NULL;
+    jboolean res = JNI_FALSE;
+
+    if (mCanUse == NULL) {
+        const char* sign = "(Ljava/lang/Class;)Z";
+        mCanUse = get_method(env, jlrM(env), "canUse", sign);
+    }
+    res = JNI_ENV_PTR(env)->CallBooleanMethod(JNI_ENV_ARG(env, module),
+                                              mCanUse, service);
+    return res;
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_AddModuleUsesAndProvidesTest_checkUses(JNIEnv *env,
+                                                      jclass  cls,
+                                                      jobject baseModule,
+                                                      jclass  service) {
+    jvmtiError err = JVMTI_ERROR_NONE;
+    jboolean used = JNI_FALSE;
+
+    // Add a service to use to NULL module
+    printf("Check #UN1:\n");
+    err = (*jvmti)->AddModuleUses(jvmti, NULL, service);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#UN1: jvmtiError from AddModuleUses: %d\n", err);
+        throw_exc(env, "Check #UN1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL");
+        return FAILED;
+    }
+
+    // Add NULL service to use to baseModule
+    printf("Check #UN2:\n");
+    err = (*jvmti)->AddModuleUses(jvmti, baseModule, NULL);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#UN2: jvmtiError from AddModuleUses: %d\n", err);
+        throw_exc(env, "Check #UN2: failed to return JVMTI_ERROR_NULL_POINTER for service==NULL");
+        return FAILED;
+    }
+
+    // Add service to use to invalid module (cls)
+    printf("Check #UI1:\n");
+    err = (*jvmti)->AddModuleUses(jvmti, (jobject)cls, service);
+    if (err != JVMTI_ERROR_INVALID_MODULE) {
+        printf("#UI1: jvmtiError from AddModuleUses: %d\n", err);
+        throw_exc(env, "Check #UI1: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid module");
+        return FAILED;
+    }
+
+    // Add invalid service (thisModule) to use to baseModule
+    printf("Check #UI2:\n");
+    err = (*jvmti)->AddModuleUses(jvmti, baseModule, baseModule);
+    if (err != JVMTI_ERROR_INVALID_CLASS) {
+        printf("#UI2: jvmtiError from AddModuleUses: %d\n", err);
+        throw_exc(env, "Check #UI2: did not get expected JVMTI_ERROR_INVALID_CLASS for invalid service");
+        return FAILED;
+    }
+
+    // Check if the service can not be used
+    printf("Check #UC1:\n");
+    used = can_use_service(env, baseModule, service);
+    if (used != JNI_FALSE) {
+        throw_exc(env, "Check #UC1: unexpected use of service");
+        return FAILED;
+    }
+
+    // Add uses of a correct service
+    printf("Check #UC2:\n");
+    err = (*jvmti)->AddModuleUses(jvmti, baseModule, service);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("#UC2: jvmtiError from AddModuleUses: %d\n", err);
+        throw_exc(env, "Check #UC2: got unexpected JVMTI error");
+        return FAILED;
+    }
+
+    // Check if the service can not be used
+    printf("Check #UC3:\n");
+    used = can_use_service(env, baseModule, service);
+    if (used == JNI_FALSE) {
+        throw_exc(env, "Check #UC3: service can not be used unexpectedly");
+        return FAILED;
+    }
+    fflush(0);
+    return PASSED;
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_AddModuleUsesAndProvidesTest_checkProvides(JNIEnv *env,
+                                                          jclass  cls,
+                                                          jobject baseModule,
+                                                          jclass  service,
+                                                          jclass  serviceImpl) {
+   jvmtiError err = JVMTI_ERROR_NONE;
+   jboolean provided = JNI_FALSE;
+
+    // Add provides to NULL module
+    printf("Check #PN1:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, NULL, service, serviceImpl);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#PN1: jvmtiError from AddModuleProvides: %d\n", err);
+        throw_exc(env, "Check #PN1: failed to return JVMTI_ERROR_NULL_POINTER for module==NULL");
+        return FAILED;
+    }
+
+    // Add provides with NULL service
+    printf("Check #PN2:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, baseModule, NULL, serviceImpl);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#PN2: jvmtiError from AddModuleProvides: %d\n", err);
+        throw_exc(env, "Check #PN2: failed to return JVMTI_ERROR_NULL_POINTER for service==NULL");
+        return FAILED;
+    }
+
+    // Add provides with NULL serviceImpl
+    printf("Check #PN3:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, baseModule, service, NULL);
+    if (err != JVMTI_ERROR_NULL_POINTER) {
+        printf("#PN3: jvmtiError from AddModuleProvides: %d\n", err);
+        throw_exc(env, "Check #PN3: failed to return JVMTI_ERROR_NULL_POINTER for serviceImpl==NULL");
+        return FAILED;
+    }
+
+    // Add provides to invalid module (cls)
+    printf("Check #PI1:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, (jobject)cls, service, serviceImpl);
+    if (err != JVMTI_ERROR_INVALID_MODULE) {
+        printf("#PI1: jvmtiError from AddModuleProvides: %d\n", err);
+        throw_exc(env, "Check #PI1: did not get expected JVMTI_ERROR_INVALID_MODULE for invalid module");
+        return FAILED;
+    }
+
+    // Add provides with invalid service (baseModule)
+    printf("Check #PI2:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, baseModule, baseModule, serviceImpl);
+    if (err != JVMTI_ERROR_INVALID_CLASS) {
+        printf("#PI2: jvmtiError from AddModuleProvides: %d\n", err);
+        throw_exc(env, "Check #PI2: did not get expected JVMTI_ERROR_INVALID_CLASS for invalid service");
+        return FAILED;
+    }
+
+    // Add provides with invalid serviceImpl (baseModule)
+    printf("Check #PI3:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, baseModule, service, baseModule);
+    if (err != JVMTI_ERROR_INVALID_CLASS) {
+        printf("#PI3: jvmtiError from AddModuleProvides: %d\n", err);
+        throw_exc(env, "Check #PI3: did not get expected JVMTI_ERROR_INVALID_CLASS for invalid serviceImpl");
+        return FAILED;
+    }
+
+    // Add provides to baseModule with correct service and serviceImpl
+    printf("Check #PC2:\n");
+    err = (*jvmti)->AddModuleProvides(jvmti, baseModule, service, serviceImpl);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("#PC2: jvmtiError from AddModuleExports: %d\n", err);
+        throw_exc(env, "Check #PC2: error in add provides to baseModule with correct service and serviceImpl");
+        return FAILED;
+    }
+    fflush(0);
+    return PASSED;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/hotspot/test/serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java b/hotspot/test/serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java
index 5fa6c9e..7cd5041 100644
--- a/hotspot/test/serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java
+++ b/hotspot/test/serviceability/jvmti/GetModulesInfo/JvmtiGetAllModulesTest.java
@@ -72,8 +72,7 @@
 
         // Load a new named module
         ModuleDescriptor descriptor
-                = new ModuleDescriptor.Builder(MY_MODULE_NAME)
-                .build();
+                = ModuleDescriptor.module(MY_MODULE_NAME).build();
         ModuleFinder finder = finderOf(descriptor);
         ClassLoader loader = new ClassLoader() {};
         Configuration parent = Layer.boot().configuration();
diff --git a/hotspot/test/serviceability/sa/TestInstanceKlassSize.java b/hotspot/test/serviceability/sa/TestInstanceKlassSize.java
index 4af527e..e99b2a9 100644
--- a/hotspot/test/serviceability/sa/TestInstanceKlassSize.java
+++ b/hotspot/test/serviceability/sa/TestInstanceKlassSize.java
@@ -46,6 +46,7 @@
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  * @compile -XDignore.symbol.file=true
+ *          --add-modules=jdk.hotspot.agent
  *          --add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED
  *          --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED
  *          --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED
diff --git a/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java b/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java
index f6a9c3f..abf5412 100644
--- a/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java
+++ b/hotspot/test/serviceability/sa/TestInstanceKlassSizeForInterface.java
@@ -39,6 +39,7 @@
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  * @compile -XDignore.symbol.file=true
+ *          --add-modules=jdk.hotspot.agent
  *          --add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED
  *          --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED
  *          --add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED
diff --git a/jaxp/.hgignore b/jaxp/.hgignore
index 195f7db..1c1d4fc 100644
--- a/jaxp/.hgignore
+++ b/jaxp/.hgignore
@@ -4,4 +4,3 @@
 ^drop_included/
 ^webrev
 /nbproject/private/
-^.hgtip
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index b0676a9..6d7126d 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -389,3 +389,4 @@
 99be33734ff62b75116b1202d49a4d4e1bda4226 jdk-9+144
 71558b38bad786f11350790cef7d2c6409813e91 jdk-9+145
 09eda28b98e4b9cae1d29e94f0cf1a01cc42c207 jdk-9+146
+149559dd882ddca2c78355641a46db9138b12763 jdk-9+147
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java
index 37a346e..746418b 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java
@@ -471,8 +471,7 @@
             String pn = _tfactory.getPackageName();
             assert pn != null && pn.length() > 0;
 
-            ModuleDescriptor descriptor
-                = new ModuleDescriptor.Builder(mn)
+            ModuleDescriptor descriptor = ModuleDescriptor.module(mn)
                     .requires("java.xml")
                     .exports(pn)
                     .build();
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java
index d1af91a..9b961b3 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLStreamReaderImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -607,7 +607,8 @@
         //get the new scanner state to old scanner's previous state
         fScanner.reset(fPropertyManager);
         fScanner.setPropertyManager(fPropertyManager);
-        fEntityScanner = (XMLEntityScanner)fEntityManager.getEntityScanner()  ;
+        fEntityScanner = fEntityManager.getEntityScanner();
+        fEntityScanner.registerListener(fScanner);
         fEntityManager.fCurrentEntity.mayReadChunks = true;
         fScanner.setScannerState(XMLEvent.START_DOCUMENT);
 
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java
index 001b682..a53f93d 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/datatype/DatatypeFactory.java
@@ -30,6 +30,7 @@
 import java.util.GregorianCalendar;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl;
 
 /**
  * Factory that creates new {@code javax.xml.datatype} {@code Object}s that map XML to/from Java {@code Object}s.
@@ -136,6 +137,20 @@
     }
 
     /**
+     * Creates a new instance of the {@code DatatypeFactory} {@linkplain
+     * #DATATYPEFACTORY_IMPLEMENTATION_CLASS builtin system-default
+     * implementation}.
+     *
+     * @return A new instance of the {@code DatatypeFactory} builtin
+     *         system-default implementation.
+     *
+     * @since 9
+     */
+    public static DatatypeFactory newDefaultInstance() {
+        return new DatatypeFactoryImpl();
+    }
+
+    /**
      * Obtain a new instance of a {@code DatatypeFactory}.
      *
      * <p>The implementation resolution mechanisms are <a href="#DatatypeFactory.newInstance">defined</a> in this
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/parsers/DocumentBuilderFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/parsers/DocumentBuilderFactory.java
index 71fed6c..f04eccf 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/parsers/DocumentBuilderFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/parsers/DocumentBuilderFactory.java
@@ -25,6 +25,7 @@
 
 package javax.xml.parsers;
 
+import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
 import javax.xml.validation.Schema;
 
 /**
@@ -54,6 +55,19 @@
     }
 
     /**
+     * Creates a new instance of the {@code DocumentBuilderFactory} builtin
+     * system-default implementation.
+     *
+     * @return A new instance of the {@code DocumentBuilderFactory} builtin
+     *         system-default implementation.
+     *
+     * @since 9
+     */
+    public static DocumentBuilderFactory newDefaultInstance() {
+        return new DocumentBuilderFactoryImpl();
+    }
+
+    /**
      * Obtain a new instance of a
      * {@code DocumentBuilderFactory}. This static method creates
      * a new factory instance.
@@ -93,7 +107,8 @@
      * </li>
      * <li>
      * <p>
-     * Otherwise, the system-default implementation is returned.
+     * Otherwise, the {@linkplain #newDefaultInstance() system-default}
+     * implementation is returned.
      * </li>
      * </ul>
      *
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java
index 1732047..08deb51 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/parsers/SAXParserFactory.java
@@ -25,6 +25,7 @@
 
 package javax.xml.parsers;
 
+import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
 import javax.xml.validation.Schema;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXNotRecognizedException;
@@ -59,6 +60,19 @@
     }
 
     /**
+     * Creates a new instance of the {@code SAXParserFactory} builtin
+     * system-default implementation.
+     *
+     * @return A new instance of the {@code SAXParserFactory} builtin
+     *         system-default implementation.
+     *
+     * @since 9
+     */
+    public static SAXParserFactory newDefaultInstance() {
+        return new SAXParserFactoryImpl();
+    }
+
+    /**
      * Obtain a new instance of a {@code SAXParserFactory}. This
      * static method creates a new factory instance
      * This method uses the following ordered lookup procedure to determine
@@ -97,7 +111,8 @@
      * </li>
      * <li>
      * <p>
-     * Otherwise the system-default implementation is returned.
+     * Otherwise, the {@linkplain #newDefaultInstance() system-default}
+     * implementation is returned.
      * </li>
      * </ul>
      *
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventFactory.java
index 1ec4d38..37e5f7a 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventFactory.java
@@ -27,6 +27,7 @@
  */
 
 package javax.xml.stream;
+import com.sun.xml.internal.stream.events.XMLEventFactoryImpl;
 import java.util.Iterator;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
@@ -54,6 +55,19 @@
 
 
   /**
+   * Creates a new instance of the {@code XMLEventFactory} builtin
+   * system-default implementation.
+   *
+   * @return A new instance of the {@code XMLEventFactory} builtin
+   *         system-default implementation.
+   *
+   * @since 9
+   */
+  public static XMLEventFactory newDefaultFactory() {
+      return new XMLEventFactoryImpl();
+  }
+
+  /**
    * Creates a new instance of the factory in exactly the same manner as the
    * {@link #newFactory()} method.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
@@ -108,7 +122,8 @@
    * </li>
    * <li>
    *   <p>
-   *   Otherwise, the system-default implementation is returned.
+   *   Otherwise, the {@linkplain #newDefaultFactory() system-default}
+   *   implementation is returned.
    * </li>
    * </ul>
    * <p>
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLInputFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLInputFactory.java
index 191a6df..cb936ac 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLInputFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLInputFactory.java
@@ -28,6 +28,7 @@
 
 package javax.xml.stream;
 
+import com.sun.xml.internal.stream.XMLInputFactoryImpl;
 import javax.xml.stream.util.XMLEventAllocator;
 import javax.xml.transform.Source;
 
@@ -144,6 +145,19 @@
   protected XMLInputFactory(){}
 
   /**
+   * Creates a new instance of the {@code XMLInputFactory} builtin
+   * system-default implementation.
+   *
+   * @return A new instance of the {@code XMLInputFactory} builtin
+   *         system-default implementation.
+   *
+   * @since 9
+   */
+  public static XMLInputFactory newDefaultFactory() {
+      return new XMLInputFactoryImpl();
+  }
+
+  /**
    * Creates a new instance of the factory in exactly the same manner as the
    * {@link #newFactory()} method.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
@@ -195,7 +209,8 @@
    *   ClassLoader#getSystemClassLoader() system class loader} will be used.
    * </li>
    * <li>
-   * <p>Otherwise, the system-default implementation is returned.
+   * <p>Otherwise, the {@linkplain #newDefaultFactory() system-default}
+   *    implementation is returned.
    * </li>
    * </ul>
    * <p>
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLOutputFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLOutputFactory.java
index caa2305..939cb67 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLOutputFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLOutputFactory.java
@@ -28,6 +28,7 @@
 
 package javax.xml.stream;
 
+import com.sun.xml.internal.stream.XMLOutputFactoryImpl;
 import javax.xml.transform.Result;
 
 /**
@@ -121,6 +122,19 @@
   protected XMLOutputFactory(){}
 
   /**
+   * Creates a new instance of the {@code XMLOutputFactory} builtin
+   * system-default implementation.
+   *
+   * @return A new instance of the {@code XMLOutputFactory} builtin
+   *         system-default implementation.
+   *
+   * @since 9
+   */
+  public static XMLOutputFactory newDefaultFactory() {
+      return new XMLOutputFactoryImpl();
+  }
+
+  /**
    * Creates a new instance of the factory in exactly the same manner as the
    * {@link #newFactory()} method.
    * @throws FactoryConfigurationError if an instance of this factory cannot be loaded
@@ -175,7 +189,8 @@
    * </li>
    * <li>
    *   <p>
-   *   Otherwise, the system-default implementation is returned.
+   *   Otherwise, the {@linkplain #newDefaultFactory() system-default}
+   *   implementation is returned.
    * </li>
    * </ul>
    * <p>
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerFactory.java
index b095782..44774e4 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/transform/TransformerFactory.java
@@ -25,6 +25,8 @@
 
 package javax.xml.transform;
 
+import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
+
 /**
  * <p>A TransformerFactory instance can be used to create
  * {@link javax.xml.transform.Transformer} and
@@ -51,6 +53,19 @@
 
 
     /**
+     * Creates a new instance of the {@code TransformerFactory} builtin
+     * system-default implementation.
+     *
+     * @return A new instance of the {@code TransformerFactory} builtin
+     *         system-default implementation.
+     *
+     * @since 9
+     */
+    public static TransformerFactory newDefaultInstance() {
+        return TransformerFactoryImpl.newTransformerFactoryNoServiceLoader();
+    }
+
+    /**
      * Obtain a new instance of a {@code TransformerFactory}.
      * This static method creates a new factory instance.
      * <p>
@@ -89,7 +104,8 @@
      * </li>
      * <li>
      * <p>
-     *   Otherwise, the system-default implementation is returned.
+     *   Otherwise, the {@linkplain #newDefaultInstance() system-default}
+     *   implementation is returned.
      * </li>
      * </ul>
      *
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/validation/SchemaFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/validation/SchemaFactory.java
index 8152b67..2bcc73e 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/validation/SchemaFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/validation/SchemaFactory.java
@@ -25,6 +25,7 @@
 
 package javax.xml.validation;
 
+import com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory;
 import java.io.File;
 import java.net.URL;
 import javax.xml.transform.Source;
@@ -124,6 +125,24 @@
     }
 
     /**
+     * Creates a new instance of the {@code SchemaFactory} builtin
+     * system-default implementation.
+     *
+     * @implSpec The {@code SchemaFactory} builtin
+     * system-default implementation is only required to support the
+     * <a href="http://www.w3.org/TR/xmlschema-1">W3C XML Schema 1.0</a>,
+     * but may support additional <a href="#schemaLanguage">schema languages</a>.
+     *
+     * @return A new instance of the {@code SchemaFactory} builtin
+     *         system-default implementation.
+     *
+     * @since 9
+     */
+    public static SchemaFactory newDefaultInstance() {
+        return XMLSchemaFactory.newXMLSchemaFactoryNoServiceLoader();
+    }
+
+    /**
      * Lookup an implementation of the {@code SchemaFactory} that supports the specified
      * schema language and return it.
      *
@@ -179,7 +198,8 @@
      *   <li>
      *     <p>
      *     Platform default {@code SchemaFactory} is located
-     *     in a implementation specific way. There must be a platform default
+     *     in an implementation specific way. There must be a
+     *     {@linkplain #newDefaultInstance() platform default}
      *     {@code SchemaFactory} for W3C XML Schema.
      *   </li>
      * </ol>
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
index 220e6ea..a5b0a47 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
@@ -25,6 +25,8 @@
 
 package javax.xml.xpath;
 
+import com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl;
+
 /**
  * <p>An {@code XPathFactory} instance can be used to create
  * {@link javax.xml.xpath.XPath} objects.</p>
@@ -74,6 +76,25 @@
     }
 
     /**
+     * Creates a new instance of the {@code XPathFactory} builtin
+     * system-default implementation.
+     *
+     * @implSpec The {@code XPathFactory} builtin
+     * system-default implementation is only required to support the
+     * {@link #DEFAULT_OBJECT_MODEL_URI default object model}, the
+     * {@linkplain org.w3c.dom W3C DOM}, but may support additional
+     * object models.
+     *
+     * @return A new instance of the {@code XPathFactory} builtin
+     *         system-default implementation.
+     *
+     * @since 9
+     */
+    public static XPathFactory newDefaultInstance() {
+        return XPathFactoryImpl.newXPathFactoryNoServiceLoader();
+    }
+
+    /**
      * <p>Get a new {@code XPathFactory} instance using the default object model,
      * {@link #DEFAULT_OBJECT_MODEL_URI},
      * the W3C DOM.</p>
@@ -153,8 +174,11 @@
     *   </li>
     *   <li>
     *     <p>
-    *     Platform default {@code XPathFactory} is located in a platform specific way.
-    *     There must be a platform default XPathFactory for the W3C DOM, i.e. {@link #DEFAULT_OBJECT_MODEL_URI}.
+    *     Platform default {@code XPathFactory} is located in a platform
+    *     specific way.
+    *     There must be a {@linkplain #newDefaultInstance() platform default}
+    *     {@code XPathFactory} for the W3C DOM, i.e.
+    *     {@link #DEFAULT_OBJECT_MODEL_URI}.
     *   </li>
     * </ol>
     * <p>If everything fails, an {@code XPathFactoryConfigurationException} will be thrown.
diff --git a/jaxp/src/jdk.xml.dom/share/classes/module-info.java b/jaxp/src/jdk.xml.dom/share/classes/module-info.java
index af8529c..6828629 100644
--- a/jaxp/src/jdk.xml.dom/share/classes/module-info.java
+++ b/jaxp/src/jdk.xml.dom/share/classes/module-info.java
@@ -24,7 +24,7 @@
  */
 
 module jdk.xml.dom {
-    requires public java.xml;
+    requires transitive java.xml;
     exports org.w3c.dom.css;
     exports org.w3c.dom.html;
     exports org.w3c.dom.stylesheets;
diff --git a/jaxp/test/TEST.ROOT b/jaxp/test/TEST.ROOT
index 11ad18d..5f7295e 100644
--- a/jaxp/test/TEST.ROOT
+++ b/jaxp/test/TEST.ROOT
@@ -23,7 +23,7 @@
 groups=TEST.groups
 
 # Minimum jtreg version
-requiredVersion=4.2 b03
+requiredVersion=4.2 b04
 
 # Use new module options
 useNewOptions=true
diff --git a/jaxp/test/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java b/jaxp/test/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java
index b536815..f9e25de 100644
--- a/jaxp/test/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java
@@ -45,6 +45,7 @@
  * @test
  * @bug 8077931
  * @library /javax/xml/jaxp/libs
+ * @modules java.xml/javax.xml.catalog:open
  * @run testng/othervm -DrunSecMngr=true catalog.DeferFeatureTest
  * @run testng/othervm catalog.DeferFeatureTest
  * @summary This case tests whether the catalogs specified in delegateSystem,
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/FactoryNewInstanceTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/FactoryNewInstanceTest.java
index 26aada3..f00259f 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/FactoryNewInstanceTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/FactoryNewInstanceTest.java
@@ -24,6 +24,9 @@
 package javax.xml.datatype.ptests;
 
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
 
 import javax.xml.datatype.DatatypeConfigurationException;
 import javax.xml.datatype.DatatypeFactory;
@@ -37,6 +40,7 @@
 
 /*
  * @test
+ * @bug 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.datatype.ptests.FactoryNewInstanceTest
  * @run testng/othervm javax.xml.datatype.ptests.FactoryNewInstanceTest
@@ -45,13 +49,30 @@
 @Listeners({jaxp.library.BasePolicy.class})
 public class FactoryNewInstanceTest {
 
-    private static final String DATATYPE_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl";
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl";
+    private static final String DATATYPE_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
 
     @DataProvider(name = "parameters")
     public Object[][] getValidateParameters() {
         return new Object[][] { { DATATYPE_FACTORY_CLASSNAME, null }, { DATATYPE_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
     }
 
+    /**
+     * Test if newDefaultInstance() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        DatatypeFactory dtf1 = DatatypeFactory.newDefaultInstance();
+        DatatypeFactory dtf2 = DatatypeFactory.newInstance();
+        assertNotSame(dtf1, dtf2, "same instance returned:");
+        assertSame(dtf1.getClass(), dtf2.getClass(),
+                  "unexpected class mismatch for newDefaultInstance():");
+        assertEquals(dtf1.getClass().getName(), DEFAULT_IMPL_CLASS);
+    }
+
     /*
      * test for DatatypeFactory.newInstance(java.lang.String factoryClassName,
      * java.lang.ClassLoader classLoader) factoryClassName points to correct
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java
index bc5cc4c..c4d1aff 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java
@@ -34,6 +34,8 @@
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertNotSame;
 
 import java.io.BufferedReader;
 import java.io.Closeable;
@@ -66,7 +68,7 @@
 import org.xml.sax.helpers.DefaultHandler;
 
 /**
- * @bug 8080907
+ * @bug 8080907 8169778
  * This checks the methods of DocumentBuilderFactoryImpl.
  */
 /*
@@ -77,10 +79,17 @@
  */
 @Listeners({jaxp.library.FilePolicy.class})
 public class DocumentBuilderFactoryTest {
+
+    /**
+     * DocumentBuilderFactory builtin system-default implementation class name.
+     */
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl";
+
     /**
      * DocumentBuilderFactory implementation class name.
      */
-    private static final String DOCUMENT_BUILDER_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl";
+    private static final String DOCUMENT_BUILDER_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
 
     /**
      * Provide valid DocumentBuilderFactory instantiation parameters.
@@ -93,6 +102,21 @@
     }
 
     /**
+     * Test if newDefaultInstance() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        DocumentBuilderFactory dbf1 = DocumentBuilderFactory.newDefaultInstance();
+        DocumentBuilderFactory dbf2 = DocumentBuilderFactory.newInstance();
+        assertNotSame(dbf1, dbf2, "same instance returned:");
+        assertSame(dbf1.getClass(), dbf2.getClass(),
+                  "unexpected class mismatch for newDefaultInstance():");
+        assertEquals(dbf1.getClass().getName(), DEFAULT_IMPL_CLASS);
+    }
+
+    /**
      * Test for DocumentBuilderFactory.newInstance(java.lang.String
      * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
      * points to correct implementation of
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXParserFactTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXParserFactTest.java
index c294abe..2effec0 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXParserFactTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXParserFactTest.java
@@ -24,6 +24,9 @@
 package javax.xml.parsers.ptests;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
 
 import javax.xml.parsers.SAXParserFactory;
 
@@ -35,6 +38,7 @@
  */
 /*
  * @test
+ * @bug 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.parsers.ptests.SAXParserFactTest
  * @run testng/othervm javax.xml.parsers.ptests.SAXParserFactTest
@@ -48,6 +52,23 @@
     private static final String VALIDATION = "http://xml.org/sax/features/validation";
     private static final String EXTERNAL_G_ENTITIES = "http://xml.org/sax/features/external-general-entities";
     private static final String EXTERNAL_P_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl";
+
+    /**
+     * Test if newDefaultInstance() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        SAXParserFactory spf1 = SAXParserFactory.newDefaultInstance();
+        SAXParserFactory spf2 = SAXParserFactory.newInstance();
+        assertNotSame(spf1, spf2, "same instance returned:");
+        assertSame(spf1.getClass(), spf2.getClass(),
+                  "unexpected class mismatch for newDefaultInstance():");
+        assertEquals(spf1.getClass().getName(), DEFAULT_IMPL_CLASS);
+    }
 
     /**
      * Test if newSAXParser() method returns SAXParser.
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLEventFactoryNewInstanceTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLEventFactoryNewInstanceTest.java
index b272cd1..645a26e 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLEventFactoryNewInstanceTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLEventFactoryNewInstanceTest.java
@@ -27,6 +27,9 @@
 import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
 
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
 
 import javax.xml.stream.XMLEventFactory;
 
@@ -38,6 +41,7 @@
 
 /*
  * @test
+ * @bug 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.stream.ptests.XMLEventFactoryNewInstanceTest
  * @run testng/othervm javax.xml.stream.ptests.XMLEventFactoryNewInstanceTest
@@ -46,12 +50,31 @@
 @Listeners({jaxp.library.BasePolicy.class})
 public class XMLEventFactoryNewInstanceTest {
 
-    private static final String XMLEVENT_FACTORY_CLASSNAME = "com.sun.xml.internal.stream.events.XMLEventFactoryImpl";
-    private static final String XMLEVENT_FACRORY_ID = "javax.xml.stream.XMLEventFactory";
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.xml.internal.stream.events.XMLEventFactoryImpl";
+    private static final String XMLEVENT_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
+    private static final String XMLEVENT_FACTORY_ID = "javax.xml.stream.XMLEventFactory";
 
     @DataProvider(name = "parameters")
     public Object[][] getValidateParameters() {
-        return new Object[][] { { XMLEVENT_FACRORY_ID, null }, { XMLEVENT_FACRORY_ID, this.getClass().getClassLoader() } };
+        return new Object[][] {
+            { XMLEVENT_FACTORY_ID, null },
+            { XMLEVENT_FACTORY_ID, this.getClass().getClassLoader() } };
+    }
+
+    /**
+     * Test if newDefaultFactory() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        XMLEventFactory ef1 = XMLEventFactory.newDefaultFactory();
+        XMLEventFactory ef2 = XMLEventFactory.newFactory();
+        assertNotSame(ef1, ef2, "same instance returned:");
+        assertSame(ef1.getClass(), ef2.getClass(),
+                  "unexpected class mismatch for newDefaultFactory():");
+        assertEquals(ef1.getClass().getName(), DEFAULT_IMPL_CLASS);
     }
 
     /*
@@ -62,12 +85,12 @@
      */
     @Test(dataProvider = "parameters")
     public void testNewFactory(String factoryId, ClassLoader classLoader) {
-        setSystemProperty(XMLEVENT_FACRORY_ID, XMLEVENT_FACTORY_CLASSNAME);
+        setSystemProperty(XMLEVENT_FACTORY_ID, XMLEVENT_FACTORY_CLASSNAME);
         try {
             XMLEventFactory xef = XMLEventFactory.newFactory(factoryId, classLoader);
             assertNotNull(xef);
         } finally {
-            clearSystemProperty(XMLEVENT_FACRORY_ID);
+            clearSystemProperty(XMLEVENT_FACTORY_ID);
         }
     }
 
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLInputFactoryNewInstanceTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLInputFactoryNewInstanceTest.java
index 9b77ac4..e747396 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLInputFactoryNewInstanceTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLInputFactoryNewInstanceTest.java
@@ -27,6 +27,9 @@
 import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
 
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
 
 import javax.xml.stream.XMLInputFactory;
 
@@ -38,6 +41,7 @@
 
 /*
  * @test
+ * @bug 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.stream.ptests.XMLInputFactoryNewInstanceTest
  * @run testng/othervm javax.xml.stream.ptests.XMLInputFactoryNewInstanceTest
@@ -46,12 +50,31 @@
 @Listeners({jaxp.library.BasePolicy.class})
 public class XMLInputFactoryNewInstanceTest {
 
-    private static final String XMLINPUT_FACTORY_CLASSNAME = "com.sun.xml.internal.stream.XMLInputFactoryImpl";
-    private static final String XMLINPUT_FACRORY_ID = "javax.xml.stream.XMLInputFactory";
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.xml.internal.stream.XMLInputFactoryImpl";
+    private static final String XMLINPUT_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
+    private static final String XMLINPUT_FACTORY_ID = "javax.xml.stream.XMLInputFactory";
 
     @DataProvider(name = "parameters")
     public Object[][] getValidateParameters() {
-        return new Object[][] { { XMLINPUT_FACRORY_ID, null }, { XMLINPUT_FACRORY_ID, this.getClass().getClassLoader() } };
+        return new Object[][] {
+            { XMLINPUT_FACTORY_ID, null },
+            { XMLINPUT_FACTORY_ID, this.getClass().getClassLoader() } };
+    }
+
+    /**
+     * Test if newDefaultFactory() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        XMLInputFactory if1 = XMLInputFactory.newDefaultFactory();
+        XMLInputFactory if2 = XMLInputFactory.newFactory();
+        assertNotSame(if1, if2, "same instance returned:");
+        assertSame(if1.getClass(), if2.getClass(),
+                  "unexpected class mismatch for newDefaultFactory():");
+        assertEquals(if1.getClass().getName(), DEFAULT_IMPL_CLASS);
     }
 
     /*
@@ -62,12 +85,12 @@
      */
     @Test(dataProvider = "parameters")
     public void testNewFactory(String factoryId, ClassLoader classLoader) {
-        setSystemProperty(XMLINPUT_FACRORY_ID, XMLINPUT_FACTORY_CLASSNAME);
+        setSystemProperty(XMLINPUT_FACTORY_ID, XMLINPUT_FACTORY_CLASSNAME);
         try {
             XMLInputFactory xif = XMLInputFactory.newFactory(factoryId, classLoader);
             assertNotNull(xif);
         } finally {
-            clearSystemProperty(XMLINPUT_FACRORY_ID);
+            clearSystemProperty(XMLINPUT_FACTORY_ID);
         }
     }
 
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLOutputFactoryNewInstanceTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLOutputFactoryNewInstanceTest.java
new file mode 100644
index 0000000..e901977
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLOutputFactoryNewInstanceTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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 javax.xml.stream.ptests;
+
+import static jaxp.library.JAXPTestUtilities.setSystemProperty;
+import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
+
+import javax.xml.stream.XMLOutputFactory;
+
+import jaxp.library.JAXPDataProvider;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8169778
+ * @library /javax/xml/jaxp/libs
+ * @run testng/othervm -DrunSecMngr=true javax.xml.stream.ptests.XMLOutputFactoryNewInstanceTest
+ * @run testng/othervm javax.xml.stream.ptests.XMLOutputFactoryNewInstanceTest
+ * @summary Tests for XMLOutputFactory.newFactory(factoryId , classLoader)
+ */
+@Listeners({jaxp.library.BasePolicy.class})
+public class XMLOutputFactoryNewInstanceTest {
+
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.xml.internal.stream.XMLOutputFactoryImpl";
+    private static final String XMLOUTPUT_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
+    private static final String XMLOUTPUT_FACTORY_ID = "javax.xml.stream.XMLOutputFactory";
+
+    @DataProvider(name = "parameters")
+    public Object[][] getValidateParameters() {
+        return new Object[][] {
+            { XMLOUTPUT_FACTORY_ID, null },
+            { XMLOUTPUT_FACTORY_ID, this.getClass().getClassLoader() } };
+    }
+
+    /**
+     * Test if newDefaultFactory() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        XMLOutputFactory of1 = XMLOutputFactory.newDefaultFactory();
+        XMLOutputFactory of2 = XMLOutputFactory.newFactory();
+        assertNotSame(of1, of2, "same instance returned:");
+        assertSame(of1.getClass(), of2.getClass(),
+                  "unexpected class mismatch for newDefaultFactory():");
+        assertEquals(of1.getClass().getName(), DEFAULT_IMPL_CLASS);
+    }
+
+    /*
+     * test for XMLOutputFactory.newFactory(java.lang.String factoryId,
+     * java.lang.ClassLoader classLoader) factoryClassName points to correct
+     * implementation of javax.xml.stream.XMLOutputFactory , should return
+     * newInstance of XMLOutputFactory
+     */
+    @Test(dataProvider = "parameters")
+    public void testNewFactory(String factoryId, ClassLoader classLoader) {
+        setSystemProperty(XMLOUTPUT_FACTORY_ID, XMLOUTPUT_FACTORY_CLASSNAME);
+        try {
+            XMLOutputFactory xif = XMLOutputFactory.newFactory(factoryId, classLoader);
+            assertNotNull(xif);
+        } finally {
+            clearSystemProperty(XMLOUTPUT_FACTORY_ID);
+        }
+    }
+
+    /*
+     * test for XMLOutputFactory.newFactory(java.lang.String factoryClassName,
+     * java.lang.ClassLoader classLoader) factoryClassName is null , should
+     * throw NullPointerException
+     */
+    @Test(expectedExceptions = NullPointerException.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+    public void testNewFactoryNeg(String factoryId, ClassLoader classLoader) {
+        XMLOutputFactory.newFactory(factoryId, classLoader);
+    }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformerFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformerFactoryTest.java
index 5f1fbb2..ec5d2d4 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformerFactoryTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformerFactoryTest.java
@@ -28,6 +28,9 @@
 import static jaxp.library.JAXPTestUtilities.compareWithGold;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
 
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -55,6 +58,7 @@
  */
 /*
  * @test
+ * @bug 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.transform.ptests.TransformerFactoryTest
  * @run testng/othervm javax.xml.transform.ptests.TransformerFactoryTest
@@ -62,9 +66,15 @@
 @Listeners({jaxp.library.FilePolicy.class})
 public class TransformerFactoryTest {
     /**
+     * TransformerFactory builtin system-default implementation class name.
+     */
+    private static final String DEFAULT_IMPL_CLASS =
+       "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
+
+    /**
      * TransformerFactory implementation class name.
      */
-    private static final String TRANSFORMER_FACTORY_CLASSNAME = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
+    private static final String TRANSFORMER_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
 
     /**
      * Provide valid TransformerFactory instantiation parameters.
@@ -77,6 +87,21 @@
     }
 
     /**
+     * Test if newDefaultInstance() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        TransformerFactory tf1 = TransformerFactory.newDefaultInstance();
+        TransformerFactory tf2 = TransformerFactory.newInstance();
+        assertNotSame(tf1, tf2, "same instance returned:");
+        assertSame(tf1.getClass(), tf2.getClass(),
+                  "unexpected class mismatch for newDefaultInstance():");
+        assertEquals(tf1.getClass().getName(), DEFAULT_IMPL_CLASS);
+    }
+
+    /**
      * Test for TransformerFactory.newInstance(java.lang.String
      * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
      * points to correct implementation of
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
index c3a1261..920723c 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
@@ -28,6 +28,9 @@
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertEquals;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -66,7 +69,7 @@
 
 /*
  * @test
- * @bug 8080907
+ * @bug 8080907 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.validation.ptests.SchemaFactoryTest
  * @run testng/othervm javax.xml.validation.ptests.SchemaFactoryTest
@@ -102,6 +105,25 @@
                 { W3C_XML_SCHEMA_NS_URI, SCHEMA_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
     }
 
+    /**
+     * Test if newDefaultInstance() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        SchemaFactory sf1 = SchemaFactory.newDefaultInstance();
+        SchemaFactory sf2 = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+        assertNotSame(sf1, sf2, "same instance returned:");
+        assertSame(sf1.getClass(), sf2.getClass(),
+                  "unexpected class mismatch for newDefaultInstance():");
+        assertEquals(sf1.getClass().getName(), DEFAULT_IMPL_CLASS);
+        assertTrue(sf1.isSchemaLanguageSupported(W3C_XML_SCHEMA_NS_URI),
+                   "isSchemaLanguageSupported(W3C_XML_SCHEMA_NS_URI):");
+        assertFalse(sf1.isSchemaLanguageSupported(UNRECOGNIZED_NAME),
+                   "isSchemaLanguageSupported(UNRECOGNIZED_NAME):");
+    }
+
     /*
      * test for SchemaFactory.newInstance(java.lang.String schemaLanguage,
      * java.lang.String factoryClassName, java.lang.ClassLoader classLoader)
@@ -394,7 +416,10 @@
 
     private static final String UNRECOGNIZED_NAME = "http://xml.org/sax/features/namespace-prefixes";
 
-    private static final String SCHEMA_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory";
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory";
+
+    private static final String SCHEMA_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
 
     private SchemaFactory sf;
     private XMLInputFactory ifac;
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/xpath/ptests/XPathFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/xpath/ptests/XPathFactoryTest.java
index 8a9c51a..b0e7782 100644
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/xpath/ptests/XPathFactoryTest.java
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/xpath/ptests/XPathFactoryTest.java
@@ -24,7 +24,13 @@
 package javax.xml.xpath.ptests;
 
 import static javax.xml.xpath.XPathConstants.DOM_OBJECT_MODEL;
+import static javax.xml.xpath.XPathFactory.DEFAULT_OBJECT_MODEL_URI;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
 
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathFactory;
@@ -41,6 +47,7 @@
  */
 /*
  * @test
+ * @bug 8169778
  * @library /javax/xml/jaxp/libs
  * @run testng/othervm -DrunSecMngr=true javax.xml.xpath.ptests.XPathFactoryTest
  * @run testng/othervm javax.xml.xpath.ptests.XPathFactoryTest
@@ -58,9 +65,15 @@
     private static final String INVALID_URL = "http://java.sun.com/jaxp/xpath/dom1";
 
     /**
+     * XPathFactory builtin system-default implementation class name.
+     */
+    private static final String DEFAULT_IMPL_CLASS =
+        "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl";
+
+    /**
      * XPathFactory implementation class name.
      */
-    private static final String XPATH_FACTORY_CLASSNAME = "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl";
+    private static final String XPATH_FACTORY_CLASSNAME = DEFAULT_IMPL_CLASS;
 
 
     /**
@@ -74,6 +87,25 @@
     }
 
     /**
+     * Test if newDefaultInstance() method returns an instance
+     * of the expected factory.
+     * @throws Exception If any errors occur.
+     */
+    @Test
+    public void testDefaultInstance() throws Exception {
+        XPathFactory xpf1 = XPathFactory.newDefaultInstance();
+        XPathFactory xpf2 = XPathFactory.newInstance(DEFAULT_OBJECT_MODEL_URI);
+        assertNotSame(xpf1, xpf2, "same instance returned:");
+        assertSame(xpf1.getClass(), xpf2.getClass(),
+                  "unexpected class mismatch for newDefaultInstance():");
+        assertEquals(xpf1.getClass().getName(), DEFAULT_IMPL_CLASS);
+        assertTrue(xpf1.isObjectModelSupported(DEFAULT_OBJECT_MODEL_URI),
+                   "isObjectModelSupported(DEFAULT_OBJECT_MODEL_URI):");
+        assertFalse(xpf1.isObjectModelSupported(INVALID_URL),
+                   "isObjectModelSupported(INVALID_URL):");
+    }
+
+    /**
      * Test for XPathFactory.newInstance(java.lang.String uri, java.lang.String
      * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
      * points to correct implementation of javax.xml.xpath.XPathFactory , should
diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java
index ee3e3e0..35d2103 100644
--- a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java
+++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java
@@ -23,6 +23,7 @@
 
 import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
 
+import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.reflect.Layer;
 import java.lang.reflect.Module;
 import java.util.Arrays;
@@ -48,7 +49,8 @@
                 .map(xmlProviderName -> Layer.boot().findModule(xmlProviderName).get())
                 .mapToLong(
                         // services provided by the implementation in provider module
-                        provider -> provider.getDescriptor().provides().keySet().stream()
+                        provider -> provider.getDescriptor().provides().stream()
+                                .map(Provides::service)
                                 .filter(serviceName -> {
                                     allServices.remove(serviceName); // remove service provided by
                                                                      // customized module from allServices
diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/Bug8167340_1-0.xml b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/Bug8167340_1-0.xml
new file mode 100644
index 0000000..5ac75d2
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/Bug8167340_1-0.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?> 
+<messages> 
+<tty version="MDAGCQ 08 0 1A" id="464010300121400" op_system="Linux" system="DEV" channel="AMU INB" type="" originator="MUCRM1A" datetime="2016-09-21T13:38:28.324105Z"> 
+<recipient mode="To" type="Tty">NCE00ZZ</recipient> 
+<recipient mode="To" type="Tty">NC100ZZ</recipient> 
+<recipient mode="To" type="Tty">NCE60ZZ</recipient> 
+<body>TUFQHR1RRh0fU1RMHENPTR1NVUNSTTFBH1QcQVRSHR1IRUFERVJJRB8yMTA3NTgxMjkyNjU0NjI0MmE5HEJMQh0xMTU2NB1UHVBBUlQxDQoqKlBBU1NFTkdFUiBOQU1FIExJU1QqKg0KTFAvUUYxLzIxU0VQDQpTWUREWEINCjAwMSAgMDFUUkFKUkZWSy9WQldLVlVOUCBNOEZQMzQgRiAgSVggMjBTRVAgSERRMUYgICAgIA0KMDAyICAwMVVTRUlFSk5KL0VFQVpZWEdUIE04R1dKTCBGICBJWCAyMFNFUCBIRFExRiAgICAgDQowMDMgIDAyV0lMS0lOUy9KVURJIE1SUyAgN1FKUFhVIEEgIEhLIDE5REVDIFNZRFFGMDhBQSANCjAwNCAgMDJXSUxLSU5TL1BFVEVSIERSICA3UUpQWFUgQSAgSEsgMTlERUMgU1lEUUYwOEFBIA0KMDA1ICowMUxJTk5FVFQvTEVBTk5FTVJTIDM4OTkzNCBDICBISyAwNUFQUiBEWEJFSyAgICAgDQowMDYgIDAxREFWSUVTL0pFTk5JRkVSTVIgMkNNMjNOIEkgIEhLIDEzTUFSIFNXSTFHICAgICANCjAwNyAgMDJHT1VMT1BPVUxPUy9NRUxJUyAzQzhWT08gSSAgSEsgMThNQVIgU1lEUUYwOFdXIA0KMDA4ICAwMkdPVUxPUE9VTE9TL1NBTSBNIDNDOFZPTyBJICBISyAxOE1BUiBTWURRRjA4V1cgDQowMDkgIDAxTUFZRklFTEQvUkFZTU9ORCAgOEgyR0I0IEkgIEhLIDA3SkFOIFNZREE4MzIzNiANCjAxMCAgMDJNVVJSQVkvS0FUSEVSSU5FTSA2OVNWQzIgSSAgSEsgMTBERUMgU1dJMUcgICAgIA0KMDExICAwMk9IQVJFL0pBTkVNUyAgICAgIDY5U1ZDMiBJICBISyAxMERFQyBTV0kxRyAgICAgDQowMTIgIDAxUEVSS0lOUy9UUkFDRVkgTUkgWlNWQ0JIIEkgIEhLIDE4RkVCIE1FTFFGMDMwMyANCjAxMyAgMDFST0RSSUdVRVovTUFSSUEgTSA2Nlo0NlggSSAgSEsgMDdERUMgTUVMVEIzMTg2IA0KMDE0ICAwMVNFRFdJQ0svVklDVE9SSUEgIDJIWDk2QyBJICBISyAwMk1BUiBTWURRRjA4QUEgDQowMTUgIDAxRkVIRVIvR0VPUkdFIE1SICAgNTkzRjdQIFQgIEhLIDE2Tk9WIEhCQVFGMDMwMiANCjAxNiAgMDJXSEVFTEFIQU4vSEVMRU5NUiBaTktLTlggVCAgSEsgMTVGRUIgU1dJMUcgICAgIA0KMDE3ICAwMldIRUVMQUhBTi9QQVRSSUNLIFpOS0tOWCBUICBISyAxNUZFQiBTV0kxRyAgICAgDQowMTggIDAyR1JJRkZJTi9MQVVSQU1TICAgNFhUNFFZIFMgIEhLIDIxT0NUIFNXSTFHICAgICANCjAxOSAgMDJSRVlOT0xEUy9OSUNPTEFNUyA0WFQ0UVkgUyAgSEsgMjFPQ1QgU1dJMUcgICAgIA0KMDIwICAwMVJPQkVSVFNPTi9KT0hOQ0xBIDQ2M1ZZTyBTICBISyAyMkFQUiBTV0kxRyAgICAgDQowMjEgKjAxU0NIVVNDSEtFL0NIUklTVEkgNUtUWTVSIFMgIEhLIDAyTk9WIERYQkVLICAgICANCjAyMiAqMDJCVUVTQ0hFUi9JTkVTTVJTICAyUERLMkMgUSAgSEsgMDZNQVIgRFhCRUsgICAgIA0KMDIzICowMkxPSE1BTk4vTUFUVEhJQVNNIDJQREsyQyBRICBISyAwNk1BUiBEWEJFSyAgICAgDQowMjQgIDAyQUNDQVJESS9QQU9MTyBNUiAgNDc4VVhVIE8gIEhLIDAyTUFSIFJPTUlHMjIwQiANCjAyNSAgMDJBU0hCWS9TQU1BTlRIQSBEUiAzVVJGSjkgTyAgSEsgMjlNQVIgU1lEUUYwOFZWIA0KMDI2ICAwMkJFTkpBTUlOL0FMT05NUiAgIDNZVVJRWCBPICBISyAzMU1BUiBTV0kxRyAgICAgDQowMjcgIDAyQkVOSkFNSU4vSkVTU0lDQU0gM1lVUlFYIE8gIEhLIDMxTUFSIFNXSTFHICAgICANCjAyOCAgMDJCT0JJUy9NRVJMSU5EQURSICBaMzNMV1MgTyAgSEsgMjRGRUIgU1dJMUcgICAgIA0KMDI5ICAwMUJPVFRPTUxFWS9QQVVMIE1SIFlYSjJVQiBPICBISyAwMUZFQiBTWURRRjA4QUEgDQowMzAgIDA1Q0VQVVMvRVZJRSBNSVNTICAgMlVSQTdMIE8gIEhLIDA5TUFSIFNZRFFGMDhBQSANCjAzMSAgMDVDRVBVUy9KT0hOIE1SICAgICAyVVJBN0wgTyAgSEsgMDlNQVIgU1lEUUYwOEFBIA0KMDMyICAwNUNFUFVTL0xVS0EgTVIgICAgIDJVUkE3TCBPICBISyAwOU1BUiBTWURRRjA4QUEgDQowMzMgIDA1Q0VQVVMvTUlMQSBNSVNTICAgMlVSQTdMIE8gIEhLIDA5TUFSIFNZRFFGMDhBQSANCjAzNCAgMDFDSFJJU1RPUEhFUi9BWUFOVCAzOE9STzcgTyAgSEsgMDVBUFIgU1lEUUYwOEFBIA0KMDM1ICAwMUQgU0lMVkEvTUlOT0xJIE1TIDNaSkhENCBPICBISyAzMU1BUiBTWURRRjA4V1cgDQowMzYgIDAyR1JFQ08vTUlDSEVMQSBNUlMgNDc4VVhVIE8gIEhLIDAyTUFSIFJPTUlHMjIwQiANCjAzNyAgMDVISUxMUy9BTUVMSUEgTUlTUyBZRFZPRlQgTyAgSEsgMjFKQU4gU1lEUUYwOEFBIA0KMDM4ICAwNUhJTExTL0hBUlJJU09OIE1TIFlEVk9GVCBPICBISyAyMUpBTiBTWURRRjA4QUEgDQowMzkgIDA1SElMTFMvTUVMSU5EQSBNUlMgWURWT0ZUIE8gIEhLIDIxSkFOIFNZRFFGMDhBQSANCjA0MCAgMDVISUxMUy9NSUNIQUVMIE1SICBZRFZPRlQgTyAgSEsgMjFKQU4gU1lEUUYwOEFBIA0KMDQxICAwNUhJTExTL1JVQlkgTUlTUyAgIFlEVk9GVCBPICBISyAyMUpBTiBTWURRRjA4QUEgDQowNDIgIDA0SFVHSEVTL0NIUklTVE9QSEUgWVJRSVRHIE8gIEhLIDI4SkFOIFNZRFFGMDhBQSANCjA0MyAgMDRIVUdIRVMvREFWSUQgTVIgICBZUlFJVEcgTyAgSEsgMjhKQU4gU1lEUUYwOEFBIA0KMDQ0ICAwNEhVR0hFUy9KRU5OSUZFUiBNIFlSUUlURyBPICBISyAyOEpBTiBTWURRRjA4QUEgDQowNDUgIDA0SFVHSEVTL0tBVEhFUklORSAgWVJRSVRHIE8gIEhLIDI4SkFOIFNZRFFGMDhBQSANCjA0NiAgMDFJUk9OUy9KRUFORVRURSBNUyBaU1ZEV0ogTyAgSEsgMThGRUIgTUVMUUYwMzAzIA0KMDQ3ICowM0pFU1NJTUFOL0xJTFlNSVNTIDNUMkNaWCBPICBISyAyOE1BUiBEWEJFSyAgICAgDQowNDggKjAzSkVTU0lNQU4vTUFUSUxEQU0gM1QyQ1pYIE8gIEhLIDI4TUFSIERYQkVLICAgICANCjA0OSAqMDNKRVNTSU1BTi9TQVJBSE1SUyAzVDJDWlggTyAgSEsgMjhNQVIgRFhCRUsgICAgIA0KMDUwICAwM0tBTExPR0hMSUFOL0FSU0hPIDNZVTNCSyBPICBISyAwMUFQUiBTV0kxRyAgICAgDQowNTEgIDAzS0FMTE9HSExJQU4vR0FSRUggM1lVM0JLIE8gIEhLIDAxQVBSIFNXSTFHICAgICANCjA1MiAgMDNLQUxMT0dITElBTi9WSUtFTiAzWVUzQksgTyAgSEsgMDFBUFIgU1dJMUcgICAgIA0KMDUzICAwMktBTE5JTlMvUkVJTklTTVIgIFozM0xXUyBPICBISyAyNEZFQiBTV0kxRyAgICAgDQowNTQgIDAyS0VBTkUvRU1NQVNIQVJPTk0gWVBPQ1AzIE8gIEhLIDI4SkFOIFNXSTFHICAgICANCjA1NSAgMDJLRUFORS9TQVJBQUxMSVNPTiBZUE9DUDMgTyAgSEsgMjhKQU4gU1dJMUcgICAgIA0KMDU2ICAwMktJTkcvV0lMTElBTSBEUiAgIDNVUkZKOSBPICBISyAyOU1BUiBTWURRRjA4VlYgDQowNTcgIDAxS1VSVUtVTEFTVVJJWUEvTkEgMzQzVk1EIE8gIEhLIDAyQVBSIFNZRFFGMDhXVyANCjA1OCAqMDRNRVJSSVRUL0FOVEhPTllKQSA4TUZaVUggTyAgSEsgMTFKQU4gRFhCRUsgICAgIA0KMDU5ICowNE1FUlJJVFQvRUxMQVJPU0VNIDhNRlpVSCBPICBISyAxMUpBTiBEWEJFSyAgICAgDQowNjAgKjA0TUVSUklUVC9IQU5OQUhFVkUgOE1GWlVIIE8gIEhLIDExSkFOIERYQkVLICAgICANCjA2MSAgMDJNRVlSSUNLL01FTEFOSUUgTSBZOEU2S1IgTyAgSEsgMDZGRUIgU1lEUUYwOFVVIA0KMDYyICAwMk1FWVJJQ0svU0lNT04gTVIgIFk4RTZLUiBPICBISyAwNkZFQiBTWURRRjA4VVUgDQowNjMgIDAxTU9SUklTL1NURVBIQU5JRSAgMkJNUVA3IE8gIEhLIDI4RkVCIFNZRFFGMDhXVyANCjA2NCAqMDNOSUNIT0xTT04vQkVOSkFNSSAzU1lYQkIgTyAgSEsgMjhNQVIgRFhCRUsgICAgIA0KMDY1ICowM05JQ0hPTFNPTi9KQU1FU1JPIDNTWVhCQiBPICBISyAyOE1BUiBEWEJFSyAgICAgDQowNjYgKjAzTklDSE9MU09OL0tJUlNUWUwgM1NZWEJCIE8gIEhLIDI4TUFSIERYQkVLICAgICANCjA2NyAqMDRQRVJWQU4vU1VTQU5KQU5KQSA4TUZaVUggTyAgSEsgMTFKQU4gRFhCRUsgICAgIA0KMDY4ICAwMVNQRUFSUy9TQUNISUtPIE1SIDdIRklOQyBPICBISyAxM0RFQyBTWURRRjA4QUEgDQowNjkgIDA1VEFZTE9SL0FOTkVUVEUgTVMgMlVSQTdMIE8gIEhLIDA5TUFSIFNZRFFGMDhBQSANCjA3MCAgMDJCUkFETEVZL0FORFJFVyBNUiAzM0NFVVIgUCAgSEsgMDRPQ1QgU1lEUUYwOFJSIA0KMDcxICAwMkJSQURMRVkvQkVMSU5EQSBNIDMzQ0VVUiBQICBISyAwNE9DVCBTWURRRjA4UlIgDQowNzIgIDAySk9TRVBIL01JQ0hBRUwgTVIgWks3MzlPIFUgIEhLIDE0RkVCIE1FTFFGMDMwMyANCjA3MyAgMDJPQ09OTk9SL0RFSVJEUkUgTSBaSzczOU8gVSAgSEsgMTRGRUIgTUVMUUYwMzAzIA0KMDc0ICAwMkJFTkpBTUlOL0pPTkFUSEFOIDNYOTNYVSBYICBISyAzMU1BUiBTWURRRjA4VFQgDQowNzUgIDAyQkVOSkFNSU4vTElTQSBNUlMgM1g5M1hVIFggIEhLIDMxTUFSIFNZRFFGMDhUVCANCjA3NiAgMDNET05FTEFJTi9SRUJFQ0NBICAzV1BPT0kgWCAgSEsgMzBNQVIgU1lEUUYwOFJSIA0KMDc3ICAwM0RPTkVMSUFOL0pVTElBIE1JIDNXUE9PSSBYICBISyAzME1BUiBTWURRRjA4UlIgDQowNzggIDAzR09PRE1BTi9MSU5EWSBNSVMgM1dQT09JIFggIEhLIDMwTUFSIFNZRFFGMDhSUiANCjA3OSAgMDNNQU5TRklFTEQvSE9MTFkgTSA0NUJWUDIgWCAgSEsgMjFBUFIgU1lEUUYwOFVVIA0KMDgwICAwM01BTlNGSUVMRC9TVEVWRU4gIDQ1QlZQMiBYICBISyAyMUFQUiBTWURRRjA4VVUgDQowODEgIDAzTk9STUFOL0NBUk9MWU4gTUkgNDVCVlAyIFggIEhLIDIxQVBSIFNZRFFGMDhVVSANCjA4MiAgMDFGRUhFUi9DSFJJU1RJTkUgTSA1OTNERkcgWiAgSEsgMTZOT1YgSEJBUUYwMzAyIA0KU1lETEhSDQowODMgIDAxRE9PRlVTL0EgICAgICAgICAgNVA2QUVXIEMgIEhLIDI2SlVMIFNXSTFHICAgICANCjA4NCAgMDFOSUNPTEwvS0FUSEVSSU5FRCA1RE5aRVYgRCAgSEsgMjZBUFIgU1dJMUcgICAgIA0KMDg1ICAwMVNDT0xZRVIvUklDSEFSRE1SIDQzTkNUWSBEICBISyAyNkFQUiBTV0kxRyAgICAgDQowODYgIDAyQU5ERVJTT04vUkVCRUNDQSAgN0FZTzVaIEkgIEhLIDA4REVDIFNZRFFGMDhCQiANCjA4NyAgMDJCQVJXSUNLL0xJTkRBIFBSTyBZVVNPNUQgSSAgSEsgMzFKQU4gU1lEUUYwOFVVIA0KMDg4ICAwMkJBUldJQ0svT0xXWU4gTVMgIFlVU081RCBJICBISyAzMUpBTiBTWURRRjA4VVUgDQowODkgIDAyQkVOTkVUVC9BTEVYQU5ERVIgN0FZTzVaIEkgIEhLIDA4REVDIFNZRFFGMDhCQiANCjA5MCAgMDJCRU5ORVRUL0RBVklEIE1SICA3QkZGTjQgSSAgSEsgMDlERUMgU1lEUUYwOEJCIA0KMDkxICAwMkRBVy9MRVNMRVkgTVMgICAgIDdCRkZONCBJICBISyAwOURFQyBTWURRRjA4QkIgDQowOTIgIDAxSFVOVC9BTElTT04gRFIgICAgNEFFTFpCIEkgIEhLIDA1QVBSIFNZRFFGMDhVVSANCjA5MyAgMDFLT1NUT1BPVUxPUy9FTElaQSAzS1hUQ0kgSSAgSEsgMDhBUFIgSERRMVMgICAgIA0KMDk0ICAwNUxFV1RIV0FJVEUvQU5OQUJFIDNPMkFVOCBJICBISyAyNE1BUiBTWURRRjA4QUEgDQowOTUgIDA1TEVXVEhXQUlURS9CUkVUVCAgM08yQVU4IEkgIEhLIDI0TUFSIFNZRFFGMDhBQSANCjA5NiAgMDVMRVdUSFdBSVRFL0NIQVJMSSAzTzJBVTggSSAgSEsgMjRNQVIgU1lEUUYwOEFBIA0KMDk3ICAwNUxFV1RIV0FJVEUvTElTQSBNIDNPMkFVOCBJICBISyAyNE1BUiBTWURRRjA4QUEgDQowOTggIDA1TEVXVEhXQUlURS9NQURESUUgM08yQVU4IEkgIEhLIDI0TUFSIFNZRFFGMDhBQSANCjA5OSAgMDFPQlJJRU4vTUFSS01SICAgICAyTE1NMlkgSSAgSEsgMDRNQVIgU1dJMUcgICAgIA0KMTAwICAwMVNDT0xZRVIvUklDSEFSRCBNIDVFV1RBRyBJICBISyAyNkFQUiBTWURSSDMxMDAgDQoxMDEgIDAxU01BUlQvTklDSE9MQVMgTVIgN0RMSUlQIEkgIEhLIDA1RkVCIE1FTFRCMzE0NiANCjEwMiAgMDFDQU1QQkVMTC9LSU1NUlMgICA4T0JBOFUgUiAgSEsgMTJKQU4gU1dJMUcgICAgIA0KMTAzICAwMkFJVEtFTi9SSE9OQU1SUyAgIDI2WThOTCBUICBISyAxNU1BUiBTV0kxRyAgICAgDQoxMDQgIDAyQUlUS0VOL1JPQkVSVE1SICAgMjZZOE5MIFQgIEhLIDE1TUFSIFNXSTFHICAgICANCjEwNSAgMDFDSElLTy9UQU5ZQSBNSVNTICAzOU1WVU0gVCAgSEsgMDVBUFIgSEJBUUYwMzAyIA0KMTA2ICAwMUdSQUhBTS9UT0REIE1SICAgIFk2V001VCBUICBISyAwN0ZFQiBNRUxUQjMxNDYgDQoxMDcgIDAxTExFV0VMTFlOIEpPTkVTL0cgNUJSU0dEIFQgIEhLIDI1QVBSIFNZRFFGMDhXVyANCjEwOCAgMDFQRURFTi9FTElTQUJFVEhNQSA0UVFIRVIgVCAgSEsgMTRBUFIgU1dJMUcgICAgIA0KMTA5ICAwMUNBUlRFUi9NSUNIQUVMIE1SIDVDS0M5OCBTICBISyAyNUFQUiBMT05VMTIxMDIgDQoxMTAgIDAyQ0xBUksvU1VTQU4gTVJTICAgM1k5TUpVIFMgIEhLIDMxTUFSIFNZRFFGMDhWViANCjExMSAgMDJDTEFSSy9URVJFTkNFIE1SICAzWTlNSlUgUyAgSEsgMzFNQVIgU1lEUUYwOFZWIA0KMTEyICAwMkNVVEhCRVJUL0pBQ1FVRUxJIDJUMktFQiBTICBISyAwOE1BUiBTV0kxRyAgICAgDQoxMTMgIDAyQ1VUSEJFUlQvTkVJTE1SICAgMlQyS0VCIFMgIEhLIDA4TUFSIFNXSTFHICAgICANCjExNCAgMDFGRVJSQVJJL0NBUk9MSU5FICBaU1E0QkYgUyAgSEsgMThGRUIgUEFSUUYwOFdXIA0KMTE1ICAwMUhBU1NBTEwvTUFSSyBNUiAgIDRBRElORiBTICBISyAwNUFQUiBTWURRRjA4VVUgDQoxMTYgIDAxTE9ZVEVTVC9NRU1CRVIgTVIgNU8yRUVPIFMgIEhLIDA3SlVMIFNZRFFGMDhCQiANCjExNyAgMDJOT1JXT09EL1BBTUVMQU1SUyBaUjZTV1cgUyAgSEsgMThGRUIgU1dJMUcgICAgIA0KMTE4ICAwMk5PUldPT0QvUlVTU0VMTE1SIFpSNlNXVyBTICBISyAxOEZFQiBTV0kxRyAgICAgDQoxMTkgIDAxTEVBVEhFUi9BTVkgTUlTUyAgWjdQNUtDIE4gIEhLIDI1RkVCIExPTlFGMDhBQSANCjEyMCAgMDJBU0hUT04vSk9TSFVBICAgICA1S1NLODggUSAgSEsgMjlBUFIgSERRMVMgICAgIA0KMTIxICAwMUFTSFRPTi9NQVJLIExBV1JFIDVLQ1lIUiBRICBISyAyOUFQUiBIRFExUyAgICAgDQoxMjIgIDAyQVNIVE9OL1RPQlkgICAgICAgNUtTSzg4IFEgIEhLIDI5QVBSIEhEUTFTICAgICANCjEyMyAgMDVCQVJOVU0vQ0hBUkxFUyBNUiAzRkUzNEcgTyAgSEsgMThNQVIgU1lEUUYwOFdXIA0KMTI0ICAwNUJBUk5VTS9DSFJJUyBNUiAgIDNGRTM0RyBPICBISyAxOE1BUiBTWURRRjA4V1cgDQoxMjUgIDA1QkFSTlVNL0dFT1JHSUUgTVIgM0ZFMzRHIE8gIEhLIDE4TUFSIFNZRFFGMDhXVyANCjEyNiAgMDVCQVJOVU0vSEFSUlkgTVIgICAzRkUzNEcgTyAgSEsgMThNQVIgU1lEUUYwOFdXIA0KMTI3ICAwNUJBUk5VTS9NQVggTVIgICAgIDNGRTM0RyBPICBISyAxOE1BUiBTWURRRjA4V1cgDQoxMjggIDAxQk9PS0VSL0NIUklTVElORU0gWTY0Uk9UIE8gIEhLIDA1RkVCIFNXSTFHICAgICANCjEyOSAgMDJCUkFOREVOQlVSR0VSL0FNWSAyM1RMNUYgTyAgSEsgMTNNQVIgTUVMUUYwMzAzIA0KMTMwICAwMkJSQU5ERU5CVVJHRVIvSkVTIDIzVEw1RiBPICBISyAxM01BUiBNRUxRRjAzMDMgDQoxMzEgIDAyQ0FDSEEvRVJJQ0tTT04gTVIgMk5NQVlFIE8gIEhLIDA1TUFSIFNZRFRCMzI0OSANCjEzMiAgMDJDQUNIQS9ST1NFTExJRSBNUiAyTk1BWUUgTyAgSEsgMDVNQVIgU1lEVEIzMjQ5IA0KMTMzICAwNkVTUElSSVRVL0ZFUk5BTkRPIDJLTzZHTyBPICBISyAwM01BUiBTWURUQjMyNDkgDQoxMzQgIDA2RVNQSVJJVFUvTE9MSVRBIE0gMktPNkdPIE8gIEhLIDAzTUFSIFNZRFRCMzI0OSANCjEzNSAgMDRGT1JNSUNBL0FOVEhPTllNUiA2QVhEVkcgTyAgSEsgMTlOT1YgU1dJMUcgICAgIA0KMTM2ICAwNEZPUk1JQ0EvU1VTQU5KRUFOIDZBWERWRyBPICBISyAxOU5PViBTV0kxRyAgICAgDQoxMzcgIDAyR0FSTkhBTS9CUklESUUgTUkgMjlNSjJNIE8gIEhLIDE2TUFSIExPTlUxMjhXUCANCjEzOCAgMDRKT0hOL0FZREVOIERPVUdMQSA0MkNTN0cgTyAgSEsgMTlBUFIgU1lEUUYwOEFBIA0KMTM5ICAwNEpPSE4vR0VPUkdJQSBMQVVSIDQyQ1M3RyBPICBISyAxOUFQUiBTWURRRjA4QUEgDQoxNDAgIDA0Sk9ITi9OSUNIT0xBUyBKQU0gNDJDUzdHIE8gIEhLIDE5QVBSIFNZRFFGMDhBQSANCjE0MSAgMDRKT0hOL1NBTUFOVEhBIEpBTiA0MkNTN0cgTyAgSEsgMTlBUFIgU1lEUUYwOEFBIA0KMTQyICAwMkxFVkkvQ0hSSVNUT1BIRVIgIFlBRkxHSCBPICBISyAxOUpBTiBTWURUQjMyMTkgDQoxNDMgIDAyTEVWSS9LRVJSWSBNUlMgICAgWUFGTEdIIE8gIEhLIDE5SkFOIFNZRFRCMzIxOSANCjE0NCAgMDNNQUNLUy9DQVRIRVJJTkVNUyAyQVM1REUgTyAgSEsgMjdGRUIgU1dJMUcgICAgIA0KMTQ1ICAwM01BQ0tTL0pVRElUSE1TICAgIDJBUzVERSBPICBISyAyN0ZFQiBTV0kxRyAgICAgDQoxNDYgIDA0TUNDUkVESUUvQ0hFTFNFQSAgWU5IT1BKIE8gIEhLIDI3SkFOIFNZRFRCMzIxOSANCjE0NyAgMDRNQ0NSRURJRS9DUkFJRyBNUiBZTkhPUEogTyAgSEsgMjdKQU4gU1lEVEIzMjE5IA0KMTQ4ICAwNE1DQ1JFRElFL1NURVBIQU5JIFlOSE9QSiBPICBISyAyN0pBTiBTWURUQjMyMTkgDQoxNDkgIDA0TUNDUkVESUUvVEhPTUFTIE0gWU5IT1BKIE8gIEhLIDI3SkFOIFNZRFRCMzIxOSANCjE1MCAgMDZNT0pJQ0EvRUxBSU5FIE1SUyAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTUxICAwNE1VUlBIWS9BSURBTk1SICAgIDZBWERWRyBPICBISyAxOU5PViBTV0kxRyAgICAgDQoxNTIgIDA0TVVSUEhZL0pFTk5JRkVSQU4gNkFYRFZHIE8gIEhLIDE5Tk9WIFNXSTFHICAgICANCjE1MyAgMDZORVJBL1NZTFZJQSBNUyAgICAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTU0ICAwMU8gTkVJTEwvU1RFUEhBTklFIDJJWUNCVCBPICBISyAwMk1BUiBMT05RRjA4V1cgDQoxNTUgIDAyUEFMTUVSL0pBWk1JTiBNSVMgMjlNSjJNIE8gIEhLIDE2TUFSIExPTlUxMjhXUCANCjE1NiAgMDZTQU4gSlVBTi9BUVVJTElOQSAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTU3ICAwMlNIQURFWS9HQVJSWU1SICAgIFlVSkFETiBPICBISyAwMUZFQiBTV0kxRyAgICAgDQoxNTggIDAxU0hFUklEQU4vU0FSQSBNSVMgMzRUQ1lVIE8gIEhLIDAyQVBSIFNZRFFGMDhXVyANCjE1OSAgMDNTVUxMSVZBTi9DTEFJUkVNUyAyQVM1REUgTyAgSEsgMjdGRUIgU1dJMUcgICAgIA0KMTYwICAwMlRIT01BUy9LQVRIRVJJTkVNIFlVSkFETiBPICBISyAwMUZFQiBTV0kxRyAgICAgDQoxNjEgIDAxVFJFRFJFQS9HQUlMTVMgICAgMzg1VDk2IE8gIEhLIDA1QVBSIFNXSTFHICAgICANCjE2MiAgMDZWSVNUQS9BTkdFTElUQSBNUiAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTYzICAwMldFU1RMQUtFL0NIUklTVE9QIDdaSTZBRCBPICBISyAyNkRFQyBMT05VMTI4VVAgDQoxNjQgIDAyV0VTVExBS0UvSkFORVQgTVIgN1pJNkFEIE8gIEhLIDI2REVDIExPTlUxMjhVUCANCjE2NUcgMDIvMDBWRVJTQVJJICAgICAgICAzT0k4TUsgRyAgSEsgMjRNQVIgUk9NUUYwMzAxIA0KMTY2RyAyMS8wMFZFUlNBUkkgICAgICAgIDdJN0JTUiBHICBISyAxNUpBTiBST01RRjAxMjAgDQoxNjcgIDAyQkFJUkQvRklPTkEgICAgICAgMkpVN05OIFAgIEhLIDAzTUFSIEhEUUFBICAgICANCjE2OCAgMDJDVVJUSVMvUkVCRUNDQSAgICAySlU3Tk4gUCAgSEsgMDNNQVIgSERRQUEgICAgIA0KMTY5ICAwNEhBUkFQSU4vRElBTkUgTVJTIDVHMkxKSiBVICBISyAzMU9DVCBNRUxRRjAzMDMgDQoxNzAgIDA0SEFSQVBJTi9FRFlOIE1SICAgNUcyTEpKIFUgIEhLIDMxT0NUIE1FTFFGMDMwMyANCjE3MSAgMDRIQVJBUElOL0tBSVlBIE1JUyA1RzJMSkogVSAgSEsgMzFPQ1QgTUVMUUYwMzAzIA0KMTcyICAwNEhBUkFQSU4vUEFVTCBNUiAgIDVHMkxKSiBVICBISyAzMU9DVCBNRUxRRjAzMDMgDQoxNzMgIDAxQlJBTkRFTkJVUkdFUi9HQVYgMjNUTEpMIFggIEhLIDEzTUFSIE1FTFFGMDMwMyANCjE3NCAgMDFCVVJHRVNTIE9SVE9OL1NVUyBZRkhMTlkgWCAgSEsgMjJKQU4gU1lEUUYwOFdXIA0KMTc1ICAwMUZBTExPTi9HRU9SR0lBIE1JIFpIR0U0UiBYICBISyAxMUZFQiBTWURRRjA4UlIgDQoxNzYgIDAyS0lFTFkvQU5HRUxBIE1TICAgWkI2SDlWIFggIEhLIDA5RkVCIFNZRFFGMDhXVyANCjE3NyAgMDJLSU5EUkVEL1NJTU9OIE1SICA3UVRXVzggWCAgSEsgMTlERUMgU1lEUUYwOFJSIA0KMTc4ICAwMktPVkFDSC9KVUxJRSBNUyAgIDdRVFdXOCBYICBISyAxOURFQyBTWURRRjA4UlIgDQoxNzkgIDAyTUNDUkVBL1NPUEhJRSBNSVMgWkI2SDlWIFggIEhLIDA5RkVCIFNZRFFGMDhXVyANCjE4MCAgMDFXSUxTT04vQU5HRUxBIE1SUyAzV0hVN1UgWCAgSEsgMzBNQVIgQUtMUUYwOFBQIA0KMTgxICAwMkhBUkFQSU4vTkFUSEFOIE1SIDVHMk1UMiBaICBISyAzMU9DVCBNRUxRRjAzMDMgDQoxODIgIDAySEFSQVBJTi9UWUxFUiBNUiAgNUcyTVQyIFogIEhLIDMxT0NUIE1FTFFGMDMwMyANCjE4MyAgMDFIT0xFL0pJTEwgTVMgICAgICA1WDlWWEIgWiAgSEsgMTBOT1YgU1lEUUYwOFJSIA0KRFhCTEhSDQoxODQgIDAyR0VEREVTL0pBTkVUIE1SUyAgMzg0QkRHIFMgIEhLIDA3QVBSIENIQ0hGMzEwNSANCjE4NSAgMDJHRURERVMvUk9XRU4gTVIgICAzODRCREcgUyAgSEsgMDdBUFIgQ0hDSEYzMTA1IA0KMTg2ICowMU1PT05FU0FXTVkvQVBQTEFNIDJFSU01SyBOICBISyAwOE1BUiBEWEJFSyAgICAgDQoxODcgKjAyUE9SVEVSL0FNQU5EQSAgICAgMjhEWUNaIE4gIEhLIDE1TUFSIERYQkVLICAgICANCjE4OCAqMDJQT1JURVIvTklDSE9MQVMgICAyOERZQ1ogTiAgSEsgMTVNQVIgRFhCRUsgICAgIA0KMTg5ICowM0VZQVNVL0FTVEVSTVJTICAgIFo5TzNOSCBRICBISyAyNkZFQiBEWEJFSyAgICAgDQoxOTAgKjAzR0VCUkVNSUNIQUVML1NBTVMgWjlPM05IIFEgIEhLIDI2RkVCIERYQkVLICAgICANCjE5MSAqMDNTQU1TT04vRVpSQU1TVFIgICBaOU8zTkggUSAgSEsgMjZGRUIgRFhCRUsgICAgIA0KMTkyICAwMURBTklFTFMvQUJJR0FJTCAgIDRLWFlRQyBPICBISyAxMUFQUiBMT05FRDM4QUEgDQoxOTMgKjAxTUFLL1NVTVlVRU5NUiAgICAgMlU3ODlTIE8gIEhLIDA5TUFSIERYQkVLICAgICANCjE5NCAgMDJNQ0xFQU4vR0FSUllNUiAgICA0S0tESEsgTyAgSEsgMTFBUFIgU1dJMUcgICAgIA0KMTk1ICAwMk1DTEVBTi9TSE9OQU1SUyAgIDRLS0RISyBPICBISyAxMUFQUiBTV0kxRyAgICAgDQoxOTYgKjAyU0VPVy9KSUFOR0xJTk1SICAgWUNDREQ3IE8gIEhLIDIwSkFOIERYQkVLICAgICANCjE5NyAqMDJTRU9XL1pJVElOR01JU1MgICBZQ0NERDcgTyAgSEsgMjBKQU4gRFhCRUsgICAgIA0KMTk4ICowMlNNSVRIL0pBTUVTS0VWSU4gIDROU05OVyBPICBISyAxMkFQUiBEWEJFSyAgICAgDQoxOTkgKjAyU01JVEgvVFJBQ0VZQU5OICAgNE5TTk5XIE8gIEhLIDEyQVBSIERYQkVLICAgICANCjIwMCAqMDFTVVJFU0hLVU1BUi9TVUNISSA0TkRaM0cgTyAgSEsgMTJBUFIgRFhCRUsgICAgIA0KMjAxICowMVRBTi9MSVFJTk1JU1MgICAgIFk3OVk0QSBPICBISyAwNkZFQiBEWEJFSyAgICAgDQoyMDIgIDAyUFVUVEVSUy9BUk5PTERVUyAgM0lVWk00IFAgIEhLIDIxTUFSIEhEUUFBICAgICANCjIwMyAgMDJSSUVMQS9NQVJJQSAgICAgICAzSVVaTTQgUCAgSEsgMjFNQVIgSERRQUEgICAgIA0KMjA0ICAwMkhBUlJJU09OL01BTkRZIE1SIDdWM1pSVyBVICBISyAyM0RFQyBCS0tRRjA4UlIgDQoyMDUgIDAySEFSUklTT04vTklDSE9MQVMgN1YzWlJXIFUgIEhLIDIzREVDIEJLS1FGMDhSUiANCkVORCBPRiBESVNQTEFZHFJORx0dTEkfMRxTVFgdVEJSHEVRTh0xHEVRTh01HFJORx0dTEkfMh8yMTIcRVFOHTIcRFVNHEFUQx0dVG8cQ09NHU5DRTAwWlofVBxBVEMdHVRvHENPTR1OQzEwMFpaH1QcQVRDHR1UbxxDT00dTkNFNjBaWh9UHA==</body> 
+</tty> 
+</messages> 
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/Bug8167340_1-1.xml b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/Bug8167340_1-1.xml
new file mode 100644
index 0000000..2cc90b6
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/Bug8167340_1-1.xml
@@ -0,0 +1,9 @@
+<?xml version="1.1" encoding="utf-8"?> 
+<messages> 
+<tty version="MDAGCQ 08 0 1A" id="464010300121400" op_system="Linux" system="DEV" channel="AMU INB" type="" originator="MUCRM1A" datetime="2016-09-21T13:38:28.324105Z"> 
+<recipient mode="To" type="Tty">NCE00ZZ</recipient> 
+<recipient mode="To" type="Tty">NC100ZZ</recipient> 
+<recipient mode="To" type="Tty">NCE60ZZ</recipient> 
+<body>TUFQHR1RRh0fU1RMHENPTR1NVUNSTTFBH1QcQVRSHR1IRUFERVJJRB8yMTA3NTgxMjkyNjU0NjI0MmE5HEJMQh0xMTU2NB1UHVBBUlQxDQoqKlBBU1NFTkdFUiBOQU1FIExJU1QqKg0KTFAvUUYxLzIxU0VQDQpTWUREWEINCjAwMSAgMDFUUkFKUkZWSy9WQldLVlVOUCBNOEZQMzQgRiAgSVggMjBTRVAgSERRMUYgICAgIA0KMDAyICAwMVVTRUlFSk5KL0VFQVpZWEdUIE04R1dKTCBGICBJWCAyMFNFUCBIRFExRiAgICAgDQowMDMgIDAyV0lMS0lOUy9KVURJIE1SUyAgN1FKUFhVIEEgIEhLIDE5REVDIFNZRFFGMDhBQSANCjAwNCAgMDJXSUxLSU5TL1BFVEVSIERSICA3UUpQWFUgQSAgSEsgMTlERUMgU1lEUUYwOEFBIA0KMDA1ICowMUxJTk5FVFQvTEVBTk5FTVJTIDM4OTkzNCBDICBISyAwNUFQUiBEWEJFSyAgICAgDQowMDYgIDAxREFWSUVTL0pFTk5JRkVSTVIgMkNNMjNOIEkgIEhLIDEzTUFSIFNXSTFHICAgICANCjAwNyAgMDJHT1VMT1BPVUxPUy9NRUxJUyAzQzhWT08gSSAgSEsgMThNQVIgU1lEUUYwOFdXIA0KMDA4ICAwMkdPVUxPUE9VTE9TL1NBTSBNIDNDOFZPTyBJICBISyAxOE1BUiBTWURRRjA4V1cgDQowMDkgIDAxTUFZRklFTEQvUkFZTU9ORCAgOEgyR0I0IEkgIEhLIDA3SkFOIFNZREE4MzIzNiANCjAxMCAgMDJNVVJSQVkvS0FUSEVSSU5FTSA2OVNWQzIgSSAgSEsgMTBERUMgU1dJMUcgICAgIA0KMDExICAwMk9IQVJFL0pBTkVNUyAgICAgIDY5U1ZDMiBJICBISyAxMERFQyBTV0kxRyAgICAgDQowMTIgIDAxUEVSS0lOUy9UUkFDRVkgTUkgWlNWQ0JIIEkgIEhLIDE4RkVCIE1FTFFGMDMwMyANCjAxMyAgMDFST0RSSUdVRVovTUFSSUEgTSA2Nlo0NlggSSAgSEsgMDdERUMgTUVMVEIzMTg2IA0KMDE0ICAwMVNFRFdJQ0svVklDVE9SSUEgIDJIWDk2QyBJICBISyAwMk1BUiBTWURRRjA4QUEgDQowMTUgIDAxRkVIRVIvR0VPUkdFIE1SICAgNTkzRjdQIFQgIEhLIDE2Tk9WIEhCQVFGMDMwMiANCjAxNiAgMDJXSEVFTEFIQU4vSEVMRU5NUiBaTktLTlggVCAgSEsgMTVGRUIgU1dJMUcgICAgIA0KMDE3ICAwMldIRUVMQUhBTi9QQVRSSUNLIFpOS0tOWCBUICBISyAxNUZFQiBTV0kxRyAgICAgDQowMTggIDAyR1JJRkZJTi9MQVVSQU1TICAgNFhUNFFZIFMgIEhLIDIxT0NUIFNXSTFHICAgICANCjAxOSAgMDJSRVlOT0xEUy9OSUNPTEFNUyA0WFQ0UVkgUyAgSEsgMjFPQ1QgU1dJMUcgICAgIA0KMDIwICAwMVJPQkVSVFNPTi9KT0hOQ0xBIDQ2M1ZZTyBTICBISyAyMkFQUiBTV0kxRyAgICAgDQowMjEgKjAxU0NIVVNDSEtFL0NIUklTVEkgNUtUWTVSIFMgIEhLIDAyTk9WIERYQkVLICAgICANCjAyMiAqMDJCVUVTQ0hFUi9JTkVTTVJTICAyUERLMkMgUSAgSEsgMDZNQVIgRFhCRUsgICAgIA0KMDIzICowMkxPSE1BTk4vTUFUVEhJQVNNIDJQREsyQyBRICBISyAwNk1BUiBEWEJFSyAgICAgDQowMjQgIDAyQUNDQVJESS9QQU9MTyBNUiAgNDc4VVhVIE8gIEhLIDAyTUFSIFJPTUlHMjIwQiANCjAyNSAgMDJBU0hCWS9TQU1BTlRIQSBEUiAzVVJGSjkgTyAgSEsgMjlNQVIgU1lEUUYwOFZWIA0KMDI2ICAwMkJFTkpBTUlOL0FMT05NUiAgIDNZVVJRWCBPICBISyAzMU1BUiBTV0kxRyAgICAgDQowMjcgIDAyQkVOSkFNSU4vSkVTU0lDQU0gM1lVUlFYIE8gIEhLIDMxTUFSIFNXSTFHICAgICANCjAyOCAgMDJCT0JJUy9NRVJMSU5EQURSICBaMzNMV1MgTyAgSEsgMjRGRUIgU1dJMUcgICAgIA0KMDI5ICAwMUJPVFRPTUxFWS9QQVVMIE1SIFlYSjJVQiBPICBISyAwMUZFQiBTWURRRjA4QUEgDQowMzAgIDA1Q0VQVVMvRVZJRSBNSVNTICAgMlVSQTdMIE8gIEhLIDA5TUFSIFNZRFFGMDhBQSANCjAzMSAgMDVDRVBVUy9KT0hOIE1SICAgICAyVVJBN0wgTyAgSEsgMDlNQVIgU1lEUUYwOEFBIA0KMDMyICAwNUNFUFVTL0xVS0EgTVIgICAgIDJVUkE3TCBPICBISyAwOU1BUiBTWURRRjA4QUEgDQowMzMgIDA1Q0VQVVMvTUlMQSBNSVNTICAgMlVSQTdMIE8gIEhLIDA5TUFSIFNZRFFGMDhBQSANCjAzNCAgMDFDSFJJU1RPUEhFUi9BWUFOVCAzOE9STzcgTyAgSEsgMDVBUFIgU1lEUUYwOEFBIA0KMDM1ICAwMUQgU0lMVkEvTUlOT0xJIE1TIDNaSkhENCBPICBISyAzMU1BUiBTWURRRjA4V1cgDQowMzYgIDAyR1JFQ08vTUlDSEVMQSBNUlMgNDc4VVhVIE8gIEhLIDAyTUFSIFJPTUlHMjIwQiANCjAzNyAgMDVISUxMUy9BTUVMSUEgTUlTUyBZRFZPRlQgTyAgSEsgMjFKQU4gU1lEUUYwOEFBIA0KMDM4ICAwNUhJTExTL0hBUlJJU09OIE1TIFlEVk9GVCBPICBISyAyMUpBTiBTWURRRjA4QUEgDQowMzkgIDA1SElMTFMvTUVMSU5EQSBNUlMgWURWT0ZUIE8gIEhLIDIxSkFOIFNZRFFGMDhBQSANCjA0MCAgMDVISUxMUy9NSUNIQUVMIE1SICBZRFZPRlQgTyAgSEsgMjFKQU4gU1lEUUYwOEFBIA0KMDQxICAwNUhJTExTL1JVQlkgTUlTUyAgIFlEVk9GVCBPICBISyAyMUpBTiBTWURRRjA4QUEgDQowNDIgIDA0SFVHSEVTL0NIUklTVE9QSEUgWVJRSVRHIE8gIEhLIDI4SkFOIFNZRFFGMDhBQSANCjA0MyAgMDRIVUdIRVMvREFWSUQgTVIgICBZUlFJVEcgTyAgSEsgMjhKQU4gU1lEUUYwOEFBIA0KMDQ0ICAwNEhVR0hFUy9KRU5OSUZFUiBNIFlSUUlURyBPICBISyAyOEpBTiBTWURRRjA4QUEgDQowNDUgIDA0SFVHSEVTL0tBVEhFUklORSAgWVJRSVRHIE8gIEhLIDI4SkFOIFNZRFFGMDhBQSANCjA0NiAgMDFJUk9OUy9KRUFORVRURSBNUyBaU1ZEV0ogTyAgSEsgMThGRUIgTUVMUUYwMzAzIA0KMDQ3ICowM0pFU1NJTUFOL0xJTFlNSVNTIDNUMkNaWCBPICBISyAyOE1BUiBEWEJFSyAgICAgDQowNDggKjAzSkVTU0lNQU4vTUFUSUxEQU0gM1QyQ1pYIE8gIEhLIDI4TUFSIERYQkVLICAgICANCjA0OSAqMDNKRVNTSU1BTi9TQVJBSE1SUyAzVDJDWlggTyAgSEsgMjhNQVIgRFhCRUsgICAgIA0KMDUwICAwM0tBTExPR0hMSUFOL0FSU0hPIDNZVTNCSyBPICBISyAwMUFQUiBTV0kxRyAgICAgDQowNTEgIDAzS0FMTE9HSExJQU4vR0FSRUggM1lVM0JLIE8gIEhLIDAxQVBSIFNXSTFHICAgICANCjA1MiAgMDNLQUxMT0dITElBTi9WSUtFTiAzWVUzQksgTyAgSEsgMDFBUFIgU1dJMUcgICAgIA0KMDUzICAwMktBTE5JTlMvUkVJTklTTVIgIFozM0xXUyBPICBISyAyNEZFQiBTV0kxRyAgICAgDQowNTQgIDAyS0VBTkUvRU1NQVNIQVJPTk0gWVBPQ1AzIE8gIEhLIDI4SkFOIFNXSTFHICAgICANCjA1NSAgMDJLRUFORS9TQVJBQUxMSVNPTiBZUE9DUDMgTyAgSEsgMjhKQU4gU1dJMUcgICAgIA0KMDU2ICAwMktJTkcvV0lMTElBTSBEUiAgIDNVUkZKOSBPICBISyAyOU1BUiBTWURRRjA4VlYgDQowNTcgIDAxS1VSVUtVTEFTVVJJWUEvTkEgMzQzVk1EIE8gIEhLIDAyQVBSIFNZRFFGMDhXVyANCjA1OCAqMDRNRVJSSVRUL0FOVEhPTllKQSA4TUZaVUggTyAgSEsgMTFKQU4gRFhCRUsgICAgIA0KMDU5ICowNE1FUlJJVFQvRUxMQVJPU0VNIDhNRlpVSCBPICBISyAxMUpBTiBEWEJFSyAgICAgDQowNjAgKjA0TUVSUklUVC9IQU5OQUhFVkUgOE1GWlVIIE8gIEhLIDExSkFOIERYQkVLICAgICANCjA2MSAgMDJNRVlSSUNLL01FTEFOSUUgTSBZOEU2S1IgTyAgSEsgMDZGRUIgU1lEUUYwOFVVIA0KMDYyICAwMk1FWVJJQ0svU0lNT04gTVIgIFk4RTZLUiBPICBISyAwNkZFQiBTWURRRjA4VVUgDQowNjMgIDAxTU9SUklTL1NURVBIQU5JRSAgMkJNUVA3IE8gIEhLIDI4RkVCIFNZRFFGMDhXVyANCjA2NCAqMDNOSUNIT0xTT04vQkVOSkFNSSAzU1lYQkIgTyAgSEsgMjhNQVIgRFhCRUsgICAgIA0KMDY1ICowM05JQ0hPTFNPTi9KQU1FU1JPIDNTWVhCQiBPICBISyAyOE1BUiBEWEJFSyAgICAgDQowNjYgKjAzTklDSE9MU09OL0tJUlNUWUwgM1NZWEJCIE8gIEhLIDI4TUFSIERYQkVLICAgICANCjA2NyAqMDRQRVJWQU4vU1VTQU5KQU5KQSA4TUZaVUggTyAgSEsgMTFKQU4gRFhCRUsgICAgIA0KMDY4ICAwMVNQRUFSUy9TQUNISUtPIE1SIDdIRklOQyBPICBISyAxM0RFQyBTWURRRjA4QUEgDQowNjkgIDA1VEFZTE9SL0FOTkVUVEUgTVMgMlVSQTdMIE8gIEhLIDA5TUFSIFNZRFFGMDhBQSANCjA3MCAgMDJCUkFETEVZL0FORFJFVyBNUiAzM0NFVVIgUCAgSEsgMDRPQ1QgU1lEUUYwOFJSIA0KMDcxICAwMkJSQURMRVkvQkVMSU5EQSBNIDMzQ0VVUiBQICBISyAwNE9DVCBTWURRRjA4UlIgDQowNzIgIDAySk9TRVBIL01JQ0hBRUwgTVIgWks3MzlPIFUgIEhLIDE0RkVCIE1FTFFGMDMwMyANCjA3MyAgMDJPQ09OTk9SL0RFSVJEUkUgTSBaSzczOU8gVSAgSEsgMTRGRUIgTUVMUUYwMzAzIA0KMDc0ICAwMkJFTkpBTUlOL0pPTkFUSEFOIDNYOTNYVSBYICBISyAzMU1BUiBTWURRRjA4VFQgDQowNzUgIDAyQkVOSkFNSU4vTElTQSBNUlMgM1g5M1hVIFggIEhLIDMxTUFSIFNZRFFGMDhUVCANCjA3NiAgMDNET05FTEFJTi9SRUJFQ0NBICAzV1BPT0kgWCAgSEsgMzBNQVIgU1lEUUYwOFJSIA0KMDc3ICAwM0RPTkVMSUFOL0pVTElBIE1JIDNXUE9PSSBYICBISyAzME1BUiBTWURRRjA4UlIgDQowNzggIDAzR09PRE1BTi9MSU5EWSBNSVMgM1dQT09JIFggIEhLIDMwTUFSIFNZRFFGMDhSUiANCjA3OSAgMDNNQU5TRklFTEQvSE9MTFkgTSA0NUJWUDIgWCAgSEsgMjFBUFIgU1lEUUYwOFVVIA0KMDgwICAwM01BTlNGSUVMRC9TVEVWRU4gIDQ1QlZQMiBYICBISyAyMUFQUiBTWURRRjA4VVUgDQowODEgIDAzTk9STUFOL0NBUk9MWU4gTUkgNDVCVlAyIFggIEhLIDIxQVBSIFNZRFFGMDhVVSANCjA4MiAgMDFGRUhFUi9DSFJJU1RJTkUgTSA1OTNERkcgWiAgSEsgMTZOT1YgSEJBUUYwMzAyIA0KU1lETEhSDQowODMgIDAxRE9PRlVTL0EgICAgICAgICAgNVA2QUVXIEMgIEhLIDI2SlVMIFNXSTFHICAgICANCjA4NCAgMDFOSUNPTEwvS0FUSEVSSU5FRCA1RE5aRVYgRCAgSEsgMjZBUFIgU1dJMUcgICAgIA0KMDg1ICAwMVNDT0xZRVIvUklDSEFSRE1SIDQzTkNUWSBEICBISyAyNkFQUiBTV0kxRyAgICAgDQowODYgIDAyQU5ERVJTT04vUkVCRUNDQSAgN0FZTzVaIEkgIEhLIDA4REVDIFNZRFFGMDhCQiANCjA4NyAgMDJCQVJXSUNLL0xJTkRBIFBSTyBZVVNPNUQgSSAgSEsgMzFKQU4gU1lEUUYwOFVVIA0KMDg4ICAwMkJBUldJQ0svT0xXWU4gTVMgIFlVU081RCBJICBISyAzMUpBTiBTWURRRjA4VVUgDQowODkgIDAyQkVOTkVUVC9BTEVYQU5ERVIgN0FZTzVaIEkgIEhLIDA4REVDIFNZRFFGMDhCQiANCjA5MCAgMDJCRU5ORVRUL0RBVklEIE1SICA3QkZGTjQgSSAgSEsgMDlERUMgU1lEUUYwOEJCIA0KMDkxICAwMkRBVy9MRVNMRVkgTVMgICAgIDdCRkZONCBJICBISyAwOURFQyBTWURRRjA4QkIgDQowOTIgIDAxSFVOVC9BTElTT04gRFIgICAgNEFFTFpCIEkgIEhLIDA1QVBSIFNZRFFGMDhVVSANCjA5MyAgMDFLT1NUT1BPVUxPUy9FTElaQSAzS1hUQ0kgSSAgSEsgMDhBUFIgSERRMVMgICAgIA0KMDk0ICAwNUxFV1RIV0FJVEUvQU5OQUJFIDNPMkFVOCBJICBISyAyNE1BUiBTWURRRjA4QUEgDQowOTUgIDA1TEVXVEhXQUlURS9CUkVUVCAgM08yQVU4IEkgIEhLIDI0TUFSIFNZRFFGMDhBQSANCjA5NiAgMDVMRVdUSFdBSVRFL0NIQVJMSSAzTzJBVTggSSAgSEsgMjRNQVIgU1lEUUYwOEFBIA0KMDk3ICAwNUxFV1RIV0FJVEUvTElTQSBNIDNPMkFVOCBJICBISyAyNE1BUiBTWURRRjA4QUEgDQowOTggIDA1TEVXVEhXQUlURS9NQURESUUgM08yQVU4IEkgIEhLIDI0TUFSIFNZRFFGMDhBQSANCjA5OSAgMDFPQlJJRU4vTUFSS01SICAgICAyTE1NMlkgSSAgSEsgMDRNQVIgU1dJMUcgICAgIA0KMTAwICAwMVNDT0xZRVIvUklDSEFSRCBNIDVFV1RBRyBJICBISyAyNkFQUiBTWURSSDMxMDAgDQoxMDEgIDAxU01BUlQvTklDSE9MQVMgTVIgN0RMSUlQIEkgIEhLIDA1RkVCIE1FTFRCMzE0NiANCjEwMiAgMDFDQU1QQkVMTC9LSU1NUlMgICA4T0JBOFUgUiAgSEsgMTJKQU4gU1dJMUcgICAgIA0KMTAzICAwMkFJVEtFTi9SSE9OQU1SUyAgIDI2WThOTCBUICBISyAxNU1BUiBTV0kxRyAgICAgDQoxMDQgIDAyQUlUS0VOL1JPQkVSVE1SICAgMjZZOE5MIFQgIEhLIDE1TUFSIFNXSTFHICAgICANCjEwNSAgMDFDSElLTy9UQU5ZQSBNSVNTICAzOU1WVU0gVCAgSEsgMDVBUFIgSEJBUUYwMzAyIA0KMTA2ICAwMUdSQUhBTS9UT0REIE1SICAgIFk2V001VCBUICBISyAwN0ZFQiBNRUxUQjMxNDYgDQoxMDcgIDAxTExFV0VMTFlOIEpPTkVTL0cgNUJSU0dEIFQgIEhLIDI1QVBSIFNZRFFGMDhXVyANCjEwOCAgMDFQRURFTi9FTElTQUJFVEhNQSA0UVFIRVIgVCAgSEsgMTRBUFIgU1dJMUcgICAgIA0KMTA5ICAwMUNBUlRFUi9NSUNIQUVMIE1SIDVDS0M5OCBTICBISyAyNUFQUiBMT05VMTIxMDIgDQoxMTAgIDAyQ0xBUksvU1VTQU4gTVJTICAgM1k5TUpVIFMgIEhLIDMxTUFSIFNZRFFGMDhWViANCjExMSAgMDJDTEFSSy9URVJFTkNFIE1SICAzWTlNSlUgUyAgSEsgMzFNQVIgU1lEUUYwOFZWIA0KMTEyICAwMkNVVEhCRVJUL0pBQ1FVRUxJIDJUMktFQiBTICBISyAwOE1BUiBTV0kxRyAgICAgDQoxMTMgIDAyQ1VUSEJFUlQvTkVJTE1SICAgMlQyS0VCIFMgIEhLIDA4TUFSIFNXSTFHICAgICANCjExNCAgMDFGRVJSQVJJL0NBUk9MSU5FICBaU1E0QkYgUyAgSEsgMThGRUIgUEFSUUYwOFdXIA0KMTE1ICAwMUhBU1NBTEwvTUFSSyBNUiAgIDRBRElORiBTICBISyAwNUFQUiBTWURRRjA4VVUgDQoxMTYgIDAxTE9ZVEVTVC9NRU1CRVIgTVIgNU8yRUVPIFMgIEhLIDA3SlVMIFNZRFFGMDhCQiANCjExNyAgMDJOT1JXT09EL1BBTUVMQU1SUyBaUjZTV1cgUyAgSEsgMThGRUIgU1dJMUcgICAgIA0KMTE4ICAwMk5PUldPT0QvUlVTU0VMTE1SIFpSNlNXVyBTICBISyAxOEZFQiBTV0kxRyAgICAgDQoxMTkgIDAxTEVBVEhFUi9BTVkgTUlTUyAgWjdQNUtDIE4gIEhLIDI1RkVCIExPTlFGMDhBQSANCjEyMCAgMDJBU0hUT04vSk9TSFVBICAgICA1S1NLODggUSAgSEsgMjlBUFIgSERRMVMgICAgIA0KMTIxICAwMUFTSFRPTi9NQVJLIExBV1JFIDVLQ1lIUiBRICBISyAyOUFQUiBIRFExUyAgICAgDQoxMjIgIDAyQVNIVE9OL1RPQlkgICAgICAgNUtTSzg4IFEgIEhLIDI5QVBSIEhEUTFTICAgICANCjEyMyAgMDVCQVJOVU0vQ0hBUkxFUyBNUiAzRkUzNEcgTyAgSEsgMThNQVIgU1lEUUYwOFdXIA0KMTI0ICAwNUJBUk5VTS9DSFJJUyBNUiAgIDNGRTM0RyBPICBISyAxOE1BUiBTWURRRjA4V1cgDQoxMjUgIDA1QkFSTlVNL0dFT1JHSUUgTVIgM0ZFMzRHIE8gIEhLIDE4TUFSIFNZRFFGMDhXVyANCjEyNiAgMDVCQVJOVU0vSEFSUlkgTVIgICAzRkUzNEcgTyAgSEsgMThNQVIgU1lEUUYwOFdXIA0KMTI3ICAwNUJBUk5VTS9NQVggTVIgICAgIDNGRTM0RyBPICBISyAxOE1BUiBTWURRRjA4V1cgDQoxMjggIDAxQk9PS0VSL0NIUklTVElORU0gWTY0Uk9UIE8gIEhLIDA1RkVCIFNXSTFHICAgICANCjEyOSAgMDJCUkFOREVOQlVSR0VSL0FNWSAyM1RMNUYgTyAgSEsgMTNNQVIgTUVMUUYwMzAzIA0KMTMwICAwMkJSQU5ERU5CVVJHRVIvSkVTIDIzVEw1RiBPICBISyAxM01BUiBNRUxRRjAzMDMgDQoxMzEgIDAyQ0FDSEEvRVJJQ0tTT04gTVIgMk5NQVlFIE8gIEhLIDA1TUFSIFNZRFRCMzI0OSANCjEzMiAgMDJDQUNIQS9ST1NFTExJRSBNUiAyTk1BWUUgTyAgSEsgMDVNQVIgU1lEVEIzMjQ5IA0KMTMzICAwNkVTUElSSVRVL0ZFUk5BTkRPIDJLTzZHTyBPICBISyAwM01BUiBTWURUQjMyNDkgDQoxMzQgIDA2RVNQSVJJVFUvTE9MSVRBIE0gMktPNkdPIE8gIEhLIDAzTUFSIFNZRFRCMzI0OSANCjEzNSAgMDRGT1JNSUNBL0FOVEhPTllNUiA2QVhEVkcgTyAgSEsgMTlOT1YgU1dJMUcgICAgIA0KMTM2ICAwNEZPUk1JQ0EvU1VTQU5KRUFOIDZBWERWRyBPICBISyAxOU5PViBTV0kxRyAgICAgDQoxMzcgIDAyR0FSTkhBTS9CUklESUUgTUkgMjlNSjJNIE8gIEhLIDE2TUFSIExPTlUxMjhXUCANCjEzOCAgMDRKT0hOL0FZREVOIERPVUdMQSA0MkNTN0cgTyAgSEsgMTlBUFIgU1lEUUYwOEFBIA0KMTM5ICAwNEpPSE4vR0VPUkdJQSBMQVVSIDQyQ1M3RyBPICBISyAxOUFQUiBTWURRRjA4QUEgDQoxNDAgIDA0Sk9ITi9OSUNIT0xBUyBKQU0gNDJDUzdHIE8gIEhLIDE5QVBSIFNZRFFGMDhBQSANCjE0MSAgMDRKT0hOL1NBTUFOVEhBIEpBTiA0MkNTN0cgTyAgSEsgMTlBUFIgU1lEUUYwOEFBIA0KMTQyICAwMkxFVkkvQ0hSSVNUT1BIRVIgIFlBRkxHSCBPICBISyAxOUpBTiBTWURUQjMyMTkgDQoxNDMgIDAyTEVWSS9LRVJSWSBNUlMgICAgWUFGTEdIIE8gIEhLIDE5SkFOIFNZRFRCMzIxOSANCjE0NCAgMDNNQUNLUy9DQVRIRVJJTkVNUyAyQVM1REUgTyAgSEsgMjdGRUIgU1dJMUcgICAgIA0KMTQ1ICAwM01BQ0tTL0pVRElUSE1TICAgIDJBUzVERSBPICBISyAyN0ZFQiBTV0kxRyAgICAgDQoxNDYgIDA0TUNDUkVESUUvQ0hFTFNFQSAgWU5IT1BKIE8gIEhLIDI3SkFOIFNZRFRCMzIxOSANCjE0NyAgMDRNQ0NSRURJRS9DUkFJRyBNUiBZTkhPUEogTyAgSEsgMjdKQU4gU1lEVEIzMjE5IA0KMTQ4ICAwNE1DQ1JFRElFL1NURVBIQU5JIFlOSE9QSiBPICBISyAyN0pBTiBTWURUQjMyMTkgDQoxNDkgIDA0TUNDUkVESUUvVEhPTUFTIE0gWU5IT1BKIE8gIEhLIDI3SkFOIFNZRFRCMzIxOSANCjE1MCAgMDZNT0pJQ0EvRUxBSU5FIE1SUyAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTUxICAwNE1VUlBIWS9BSURBTk1SICAgIDZBWERWRyBPICBISyAxOU5PViBTV0kxRyAgICAgDQoxNTIgIDA0TVVSUEhZL0pFTk5JRkVSQU4gNkFYRFZHIE8gIEhLIDE5Tk9WIFNXSTFHICAgICANCjE1MyAgMDZORVJBL1NZTFZJQSBNUyAgICAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTU0ICAwMU8gTkVJTEwvU1RFUEhBTklFIDJJWUNCVCBPICBISyAwMk1BUiBMT05RRjA4V1cgDQoxNTUgIDAyUEFMTUVSL0pBWk1JTiBNSVMgMjlNSjJNIE8gIEhLIDE2TUFSIExPTlUxMjhXUCANCjE1NiAgMDZTQU4gSlVBTi9BUVVJTElOQSAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTU3ICAwMlNIQURFWS9HQVJSWU1SICAgIFlVSkFETiBPICBISyAwMUZFQiBTV0kxRyAgICAgDQoxNTggIDAxU0hFUklEQU4vU0FSQSBNSVMgMzRUQ1lVIE8gIEhLIDAyQVBSIFNZRFFGMDhXVyANCjE1OSAgMDNTVUxMSVZBTi9DTEFJUkVNUyAyQVM1REUgTyAgSEsgMjdGRUIgU1dJMUcgICAgIA0KMTYwICAwMlRIT01BUy9LQVRIRVJJTkVNIFlVSkFETiBPICBISyAwMUZFQiBTV0kxRyAgICAgDQoxNjEgIDAxVFJFRFJFQS9HQUlMTVMgICAgMzg1VDk2IE8gIEhLIDA1QVBSIFNXSTFHICAgICANCjE2MiAgMDZWSVNUQS9BTkdFTElUQSBNUiAyS082R08gTyAgSEsgMDNNQVIgU1lEVEIzMjQ5IA0KMTYzICAwMldFU1RMQUtFL0NIUklTVE9QIDdaSTZBRCBPICBISyAyNkRFQyBMT05VMTI4VVAgDQoxNjQgIDAyV0VTVExBS0UvSkFORVQgTVIgN1pJNkFEIE8gIEhLIDI2REVDIExPTlUxMjhVUCANCjE2NUcgMDIvMDBWRVJTQVJJICAgICAgICAzT0k4TUsgRyAgSEsgMjRNQVIgUk9NUUYwMzAxIA0KMTY2RyAyMS8wMFZFUlNBUkkgICAgICAgIDdJN0JTUiBHICBISyAxNUpBTiBST01RRjAxMjAgDQoxNjcgIDAyQkFJUkQvRklPTkEgICAgICAgMkpVN05OIFAgIEhLIDAzTUFSIEhEUUFBICAgICANCjE2OCAgMDJDVVJUSVMvUkVCRUNDQSAgICAySlU3Tk4gUCAgSEsgMDNNQVIgSERRQUEgICAgIA0KMTY5ICAwNEhBUkFQSU4vRElBTkUgTVJTIDVHMkxKSiBVICBISyAzMU9DVCBNRUxRRjAzMDMgDQoxNzAgIDA0SEFSQVBJTi9FRFlOIE1SICAgNUcyTEpKIFUgIEhLIDMxT0NUIE1FTFFGMDMwMyANCjE3MSAgMDRIQVJBUElOL0tBSVlBIE1JUyA1RzJMSkogVSAgSEsgMzFPQ1QgTUVMUUYwMzAzIA0KMTcyICAwNEhBUkFQSU4vUEFVTCBNUiAgIDVHMkxKSiBVICBISyAzMU9DVCBNRUxRRjAzMDMgDQoxNzMgIDAxQlJBTkRFTkJVUkdFUi9HQVYgMjNUTEpMIFggIEhLIDEzTUFSIE1FTFFGMDMwMyANCjE3NCAgMDFCVVJHRVNTIE9SVE9OL1NVUyBZRkhMTlkgWCAgSEsgMjJKQU4gU1lEUUYwOFdXIA0KMTc1ICAwMUZBTExPTi9HRU9SR0lBIE1JIFpIR0U0UiBYICBISyAxMUZFQiBTWURRRjA4UlIgDQoxNzYgIDAyS0lFTFkvQU5HRUxBIE1TICAgWkI2SDlWIFggIEhLIDA5RkVCIFNZRFFGMDhXVyANCjE3NyAgMDJLSU5EUkVEL1NJTU9OIE1SICA3UVRXVzggWCAgSEsgMTlERUMgU1lEUUYwOFJSIA0KMTc4ICAwMktPVkFDSC9KVUxJRSBNUyAgIDdRVFdXOCBYICBISyAxOURFQyBTWURRRjA4UlIgDQoxNzkgIDAyTUNDUkVBL1NPUEhJRSBNSVMgWkI2SDlWIFggIEhLIDA5RkVCIFNZRFFGMDhXVyANCjE4MCAgMDFXSUxTT04vQU5HRUxBIE1SUyAzV0hVN1UgWCAgSEsgMzBNQVIgQUtMUUYwOFBQIA0KMTgxICAwMkhBUkFQSU4vTkFUSEFOIE1SIDVHMk1UMiBaICBISyAzMU9DVCBNRUxRRjAzMDMgDQoxODIgIDAySEFSQVBJTi9UWUxFUiBNUiAgNUcyTVQyIFogIEhLIDMxT0NUIE1FTFFGMDMwMyANCjE4MyAgMDFIT0xFL0pJTEwgTVMgICAgICA1WDlWWEIgWiAgSEsgMTBOT1YgU1lEUUYwOFJSIA0KRFhCTEhSDQoxODQgIDAyR0VEREVTL0pBTkVUIE1SUyAgMzg0QkRHIFMgIEhLIDA3QVBSIENIQ0hGMzEwNSANCjE4NSAgMDJHRURERVMvUk9XRU4gTVIgICAzODRCREcgUyAgSEsgMDdBUFIgQ0hDSEYzMTA1IA0KMTg2ICowMU1PT05FU0FXTVkvQVBQTEFNIDJFSU01SyBOICBISyAwOE1BUiBEWEJFSyAgICAgDQoxODcgKjAyUE9SVEVSL0FNQU5EQSAgICAgMjhEWUNaIE4gIEhLIDE1TUFSIERYQkVLICAgICANCjE4OCAqMDJQT1JURVIvTklDSE9MQVMgICAyOERZQ1ogTiAgSEsgMTVNQVIgRFhCRUsgICAgIA0KMTg5ICowM0VZQVNVL0FTVEVSTVJTICAgIFo5TzNOSCBRICBISyAyNkZFQiBEWEJFSyAgICAgDQoxOTAgKjAzR0VCUkVNSUNIQUVML1NBTVMgWjlPM05IIFEgIEhLIDI2RkVCIERYQkVLICAgICANCjE5MSAqMDNTQU1TT04vRVpSQU1TVFIgICBaOU8zTkggUSAgSEsgMjZGRUIgRFhCRUsgICAgIA0KMTkyICAwMURBTklFTFMvQUJJR0FJTCAgIDRLWFlRQyBPICBISyAxMUFQUiBMT05FRDM4QUEgDQoxOTMgKjAxTUFLL1NVTVlVRU5NUiAgICAgMlU3ODlTIE8gIEhLIDA5TUFSIERYQkVLICAgICANCjE5NCAgMDJNQ0xFQU4vR0FSUllNUiAgICA0S0tESEsgTyAgSEsgMTFBUFIgU1dJMUcgICAgIA0KMTk1ICAwMk1DTEVBTi9TSE9OQU1SUyAgIDRLS0RISyBPICBISyAxMUFQUiBTV0kxRyAgICAgDQoxOTYgKjAyU0VPVy9KSUFOR0xJTk1SICAgWUNDREQ3IE8gIEhLIDIwSkFOIERYQkVLICAgICANCjE5NyAqMDJTRU9XL1pJVElOR01JU1MgICBZQ0NERDcgTyAgSEsgMjBKQU4gRFhCRUsgICAgIA0KMTk4ICowMlNNSVRIL0pBTUVTS0VWSU4gIDROU05OVyBPICBISyAxMkFQUiBEWEJFSyAgICAgDQoxOTkgKjAyU01JVEgvVFJBQ0VZQU5OICAgNE5TTk5XIE8gIEhLIDEyQVBSIERYQkVLICAgICANCjIwMCAqMDFTVVJFU0hLVU1BUi9TVUNISSA0TkRaM0cgTyAgSEsgMTJBUFIgRFhCRUsgICAgIA0KMjAxICowMVRBTi9MSVFJTk1JU1MgICAgIFk3OVk0QSBPICBISyAwNkZFQiBEWEJFSyAgICAgDQoyMDIgIDAyUFVUVEVSUy9BUk5PTERVUyAgM0lVWk00IFAgIEhLIDIxTUFSIEhEUUFBICAgICANCjIwMyAgMDJSSUVMQS9NQVJJQSAgICAgICAzSVVaTTQgUCAgSEsgMjFNQVIgSERRQUEgICAgIA0KMjA0ICAwMkhBUlJJU09OL01BTkRZIE1SIDdWM1pSVyBVICBISyAyM0RFQyBCS0tRRjA4UlIgDQoyMDUgIDAySEFSUklTT04vTklDSE9MQVMgN1YzWlJXIFUgIEhLIDIzREVDIEJLS1FGMDhSUiANCkVORCBPRiBESVNQTEFZHFJORx0dTEkfMRxTVFgdVEJSHEVRTh0xHEVRTh01HFJORx0dTEkfMh8yMTIcRVFOHTIcRFVNHEFUQx0dVG8cQ09NHU5DRTAwWlofVBxBVEMdHVRvHENPTR1OQzEwMFpaH1QcQVRDHR1UbxxDT00dTkNFNjBaWh9UHA==</body> 
+</tty> 
+</messages> 
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/StreamReaderTest.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/StreamReaderTest.java
index 39a1c85..2a8a75e 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/StreamReaderTest.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/StreamReaderTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,18 +28,45 @@
 import javax.xml.stream.XMLStreamReader;
 
 import org.testng.Assert;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Listeners;
 import org.testng.annotations.Test;
 
 /*
  * @test
+ * @bug 8167340
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  * @run testng/othervm -DrunSecMngr=true stream.XMLStreamReaderTest.StreamReaderTest
  * @run testng/othervm stream.XMLStreamReaderTest.StreamReaderTest
- * @summary Test XMLStreamReader.hasName() returns false for ENTITY_REFERENCE.
+ * @summary Verifies patches for StreamReader bugs
  */
 @Listeners({jaxp.library.FilePolicy.class})
 public class StreamReaderTest {
+    /**
+     * Verifies that after switching to a different XML Version (1.1), the parser
+     * is initialized properly (the listener was not registered in this case).
+     *
+     * @param path the path to XML source
+     * @throws Exception
+     */
+    @Test(dataProvider = "getPaths")
+    public void testSwitchXMLVersions(String path) throws Exception {
+        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+        xmlInputFactory.setProperty("javax.xml.stream.isCoalescing", true);
+        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(
+                this.getClass().getResourceAsStream(path));
+
+        while (xmlStreamReader.hasNext()) {
+            int event = xmlStreamReader.next();
+            if (event == XMLStreamConstants.START_ELEMENT) {
+                if (xmlStreamReader.getLocalName().equals("body")) {
+                    String elementText = xmlStreamReader.getElementText();
+                    Assert.assertTrue(!elementText.contains("</body>"),
+                            "Fail: elementText contains </body>");
+                }
+            }
+        }
+    }
 
     /**
      * CR 6631264 / sjsxp Issue 45:
@@ -50,7 +77,8 @@
     public void testHasNameOnEntityEvent() throws Exception {
         XMLInputFactory xif = XMLInputFactory.newInstance();
         xif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
-        XMLStreamReader r = xif.createXMLStreamReader(this.getClass().getResourceAsStream("ExternalDTD.xml"));
+        XMLStreamReader r = xif.createXMLStreamReader(
+                this.getClass().getResourceAsStream("ExternalDTD.xml"));
         while (r.next() != XMLStreamConstants.ENTITY_REFERENCE) {
             System.out.println("event type: " + r.getEventType());
             continue;
@@ -61,4 +89,15 @@
         Assert.assertFalse(r.hasName()); // fails
     }
 
+    /*
+       DataProvider: provides paths to xml sources
+       Data: path to xml source
+     */
+    @DataProvider(name = "getPaths")
+    public Object[][] getPaths() {
+        return new Object[][]{
+            {"Bug8167340_1-0.xml"},
+            {"Bug8167340_1-1.xml"}
+        };
+    }
 }
diff --git a/jaxws/.hgignore b/jaxws/.hgignore
index 94668d1..00a3c01 100644
--- a/jaxws/.hgignore
+++ b/jaxws/.hgignore
@@ -4,5 +4,4 @@
 ^drop_included/
 ^webrev
 /nbproject/private/
-^.hgtip
 .DS_Store
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 9ab79cc..e766a74 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -392,3 +392,4 @@
 92523c51d6a48b0a83912ba3cc43bc57b8159c2a jdk-9+144
 29277a4e73077269358859c43bd6658593fc0410 jdk-9+145
 1461e3e07876ea61bd0a07355a43912c9b04022a jdk-9+146
+be37411855de5b76035bef6f1b0d90d8607f2205 jdk-9+147
diff --git a/jaxws/src/java.activation/share/classes/module-info.java b/jaxws/src/java.activation/share/classes/module-info.java
index 1ba4eb1..00d40e1 100644
--- a/jaxws/src/java.activation/share/classes/module-info.java
+++ b/jaxws/src/java.activation/share/classes/module-info.java
@@ -27,7 +27,7 @@
  * Defines the JavaBeans Activation Framework (JAF) API.
  */
 module java.activation {
-    requires public java.datatransfer;
+    requires transitive java.datatransfer;
     requires java.logging;
 
     exports javax.activation;
diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/AccessorInjector.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/AccessorInjector.java
index adc2610..1be5995 100644
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/AccessorInjector.java
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/AccessorInjector.java
@@ -39,7 +39,7 @@
 
     private static final Logger logger = Util.getClassLogger();
 
-    protected static final boolean noOptimize =
+    protected static final boolean noOptimize = Runtime.version().major() >= 9 ||
         Util.getSystemProperty(ClassTailor.class.getName()+".noOptimize")!=null;
 
     static {
diff --git a/jaxws/src/java.xml.bind/share/classes/module-info.java b/jaxws/src/java.xml.bind/share/classes/module-info.java
index 708945a..1a6abaf 100644
--- a/jaxws/src/java.xml.bind/share/classes/module-info.java
+++ b/jaxws/src/java.xml.bind/share/classes/module-info.java
@@ -27,8 +27,8 @@
  * Defines the Java Architecture for XML Binding (JAXB) API.
  */
 module java.xml.bind {
-    requires public java.activation;
-    requires public java.xml;
+    requires transitive java.activation;
+    requires transitive java.xml;
     requires java.compiler;
     requires java.desktop;
     requires java.logging;
@@ -91,6 +91,10 @@
         java.xml.ws,
         jdk.xml.bind,
         jdk.xml.ws;
+    opens com.sun.xml.internal.bind.v2.model.nav to
+        java.xml.ws,
+        jdk.xml.bind,
+        jdk.xml.ws;
     exports com.sun.xml.internal.bind.v2.model.runtime to
         java.xml.ws;
     exports com.sun.xml.internal.bind.v2.model.util to
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/model/RuntimeModeler.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/model/RuntimeModeler.java
index 87d0857..29f852e 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/model/RuntimeModeler.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/model/RuntimeModeler.java
@@ -346,6 +346,7 @@
     }
 
     private boolean noWrapperGen() {
+        if (Runtime.version().major() >= 9) return true;
         Object o = config.properties().get(SuppressDocLitWrapperGeneration);
         return (o!= null && o instanceof Boolean) ? ((Boolean) o) : false;
     }
diff --git a/jaxws/src/java.xml.ws/share/classes/module-info.java b/jaxws/src/java.xml.ws/share/classes/module-info.java
index 09668d4..def2ec6 100644
--- a/jaxws/src/java.xml.ws/share/classes/module-info.java
+++ b/jaxws/src/java.xml.ws/share/classes/module-info.java
@@ -28,9 +28,9 @@
  * the Web Services Metadata API.
  */
 module java.xml.ws {
-    requires public java.activation;
-    requires public java.xml;
-    requires public java.xml.bind;
+    requires transitive java.activation;
+    requires transitive java.xml;
+    requires transitive java.xml.bind;
     requires java.annotations.common;
     requires java.desktop;
     requires java.logging;
@@ -55,6 +55,8 @@
     exports javax.xml.ws.spi.http;
     exports javax.xml.ws.wsaddressing;
 
+    opens javax.xml.ws.wsaddressing to java.xml.bind;
+
     exports com.oracle.webservices.internal.api.databinding to
         jdk.xml.ws;
     exports com.sun.xml.internal.ws.addressing to
@@ -102,10 +104,13 @@
         jdk.xml.ws;
 
     // XML document content needs to be exported
-    exports com.sun.xml.internal.ws.runtime.config to java.xml.bind;
+    opens com.sun.xml.internal.ws.runtime.config to java.xml.bind;
 
     // com.sun.xml.internal.ws.fault.SOAPFaultBuilder uses JAXBContext.newInstance
-    exports com.sun.xml.internal.ws.fault to java.xml.bind;
+    opens com.sun.xml.internal.ws.fault to java.xml.bind;
+
+    // classes passed to JAXBContext.newInstance for deep reflection
+    opens com.sun.xml.internal.ws.addressing to java.xml.bind;
 
     // JAF data handlers
     exports com.sun.xml.internal.messaging.saaj.soap to
diff --git a/jaxws/src/jdk.xml.bind/share/classes/module-info.java b/jaxws/src/jdk.xml.bind/share/classes/module-info.java
index 06faf9d..8757ce4 100644
--- a/jaxws/src/jdk.xml.bind/share/classes/module-info.java
+++ b/jaxws/src/jdk.xml.bind/share/classes/module-info.java
@@ -56,18 +56,19 @@
         jdk.xml.ws;
 
     // XML document content needs to be exported
-    exports com.sun.tools.internal.xjc.reader.xmlschema.bindinfo to
+    opens com.sun.tools.internal.xjc.reader.xmlschema.bindinfo to
         java.xml.bind;
 
     // com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo uses JAXBContext
     exports com.sun.tools.internal.xjc.generator.bean to java.xml.bind;
 
     uses com.sun.tools.internal.xjc.Plugin;
-    provides com.sun.tools.internal.xjc.Plugin with com.sun.tools.internal.xjc.addon.accessors.PluginImpl;
-    provides com.sun.tools.internal.xjc.Plugin with com.sun.tools.internal.xjc.addon.at_generated.PluginImpl;
-    provides com.sun.tools.internal.xjc.Plugin with com.sun.tools.internal.xjc.addon.code_injector.PluginImpl;
-    provides com.sun.tools.internal.xjc.Plugin with com.sun.tools.internal.xjc.addon.episode.PluginImpl;
-    provides com.sun.tools.internal.xjc.Plugin with com.sun.tools.internal.xjc.addon.locator.SourceLocationAddOn;
-    provides com.sun.tools.internal.xjc.Plugin with com.sun.tools.internal.xjc.addon.sync.SynchronizedMethodAddOn;
+    provides com.sun.tools.internal.xjc.Plugin with
+        com.sun.tools.internal.xjc.addon.accessors.PluginImpl,
+        com.sun.tools.internal.xjc.addon.at_generated.PluginImpl,
+        com.sun.tools.internal.xjc.addon.code_injector.PluginImpl,
+        com.sun.tools.internal.xjc.addon.episode.PluginImpl,
+        com.sun.tools.internal.xjc.addon.locator.SourceLocationAddOn,
+        com.sun.tools.internal.xjc.addon.sync.SynchronizedMethodAddOn;
 }
 
diff --git a/jaxws/src/jdk.xml.ws/share/classes/module-info.java b/jaxws/src/jdk.xml.ws/share/classes/module-info.java
index 9e5d44d..dbec9c5 100644
--- a/jaxws/src/jdk.xml.ws/share/classes/module-info.java
+++ b/jaxws/src/jdk.xml.ws/share/classes/module-info.java
@@ -33,6 +33,7 @@
     requires jdk.xml.bind;
 
     uses com.sun.tools.internal.ws.wscompile.Plugin;
-    provides com.sun.tools.internal.ws.wscompile.Plugin with com.sun.tools.internal.ws.wscompile.plugin.at_generated.PluginImpl;
+    provides com.sun.tools.internal.ws.wscompile.Plugin with
+        com.sun.tools.internal.ws.wscompile.plugin.at_generated.PluginImpl;
 }
 
diff --git a/jdk/.hgignore b/jdk/.hgignore
index 9710bc5..21a0a22 100644
--- a/jdk/.hgignore
+++ b/jdk/.hgignore
@@ -5,7 +5,6 @@
 /nbproject/private/
 ^make/netbeans/.*/build/
 ^make/netbeans/.*/dist/
-^.hgtip
 .DS_Store
 .*/JTreport/.*
 .*/JTwork/.*
diff --git a/jdk/.hgtags b/jdk/.hgtags
index e6027fc..fe87fc3 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -389,3 +389,4 @@
 efa71dc820eb8bd5a6c9f2f66f39c383ac3ee99d jdk-9+144
 99b7853cfbd8227c4441de4b6119c10742556840 jdk-9+145
 6e4ff59afb5d0adf21a72c4ff534326594a99e5d jdk-9+146
+c41140100bf1e5c10c7b8f3bde91c16eff7485f5 jdk-9+147
diff --git a/jdk/make/data/jdwp/jdwp.spec b/jdk/make/data/jdwp/jdwp.spec
index a144c89..bb1d21f9 100644
--- a/jdk/make/data/jdwp/jdwp.spec
+++ b/jdk/make/data/jdwp/jdwp.spec
@@ -2709,22 +2709,6 @@
             (Error VM_DEAD)
         )
     )
-    (Command CanRead=3
-        "Returns true if this module can read the source module; false otherwise."
-        "<p>Since JDWP version 9."
-        (Out
-            (moduleID module "This module.")
-            (moduleID sourceModule "The source module.")
-        )
-        (Reply
-            (boolean canRead  "true if this module can read the source module; false otherwise.")
-        )
-        (ErrorSet
-            (Error INVALID_MODULE  "This module or sourceModule is not the ID of a module.")
-            (Error NOT_IMPLEMENTED)
-            (Error VM_DEAD)
-        )
-    )
 )
 (CommandSet Event=64
     (Command Composite=100
diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk
index 475b8f1..6b5dcf9 100644
--- a/jdk/make/gensrc/GensrcMisc.gmk
+++ b/jdk/make/gensrc/GensrcMisc.gmk
@@ -108,3 +108,19 @@
 endif
 
 ################################################################################
+# Create the javax/crypto/JceSecurity.class, using the build default.
+#
+ifeq ($(UNLIMITED_CRYPTO), true)
+    JCE_DEFAULT_POLICY = unlimited
+else
+    JCE_DEFAULT_POLICY = limited
+endif
+
+$(eval $(call SetupTextFileProcessing, BUILD_JCESECURITY_JAVA, \
+    SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/javax/crypto/JceSecurity.java.template, \
+    OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/javax/crypto/JceSecurity.java, \
+    REPLACEMENTS := \
+        @@JCE_DEFAULT_POLICY@@ => $(JCE_DEFAULT_POLICY), \
+))
+
+GENSRC_JAVA_BASE += $(BUILD_JCESECURITY_JAVA)
diff --git a/jdk/make/launcher/Launcher-jdk.jconsole.gmk b/jdk/make/launcher/Launcher-jdk.jconsole.gmk
index aa07823c..6205ae6 100644
--- a/jdk/make/launcher/Launcher-jdk.jconsole.gmk
+++ b/jdk/make/launcher/Launcher-jdk.jconsole.gmk
@@ -27,7 +27,8 @@
 
 $(eval $(call SetupBuildLauncher, jconsole, \
     MAIN_CLASS := sun.tools.jconsole.JConsole, \
-    JAVA_ARGS := -Djconsole.showOutputViewer, \
+    JAVA_ARGS := --add-opens java.base/java.io=jdk.jconsole \
+		 -Djconsole.showOutputViewer, \
     CFLAGS_windows := -DJAVAW, \
     LIBS_windows := user32.lib, \
 ))
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index ed402ab..09423e4 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -287,9 +287,8 @@
         $(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
         $(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/utility \
         $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
-        $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
-        $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \
-        $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/x11 \
+        $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d \
+        $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d \
         $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
         #
 
@@ -396,7 +395,7 @@
 
 ifeq ($(USE_EXTERNAL_LCMS), true)
   # If we're using an external library, we'll just need the wrapper part.
-  # By including it explicitely, all other files will be excluded.
+  # By including it explicitly, all other files will be excluded.
   BUILD_LIBLCMS_INCLUDE_FILES := LCMS.c
 else
   BUILD_LIBLCMS_INCLUDE_FILES :=
@@ -516,24 +515,25 @@
 
   LIBAWT_HEADLESS_DIRS := $(JDK_TOPDIR)/src/java.desktop/unix/native/libawt_headless/awt \
       $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
-      $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \
-      $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/x11 \
-      $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
+      $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d \
+      $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d \
       $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
       #
 
   LIBAWT_HEADLESS_EXCLUDES := medialib
   LIBAWT_HEADLESS_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
       $(addprefix -I, $(LIBAWT_HEADLESS_DIRS)) \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \
       -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d \
       -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \
       -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
       -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
+      -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \
       -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libsunwjdga/ \
       $(LIBJAVA_HEADER_FLAGS) \
       #
@@ -862,7 +862,7 @@
 
   ifeq ($(OPENJDK_TARGET_OS), windows)
     LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/windows/native/common/awt/systemscale
-  endif	
+  endif
   LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 \
       $(addprefix -I, $(LIBSPLASHSCREEN_DIRS)) \
       $(LIBJAVA_HEADER_FLAGS) \
@@ -952,26 +952,27 @@
       $(JDK_TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt \
       $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt \
       $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
-      $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
+      $(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d \
       #
 
   LIBAWT_LWAWT_CFLAGS := \
       $(addprefix -I, $(LIBAWT_LWAWT_DIRS)) \
       -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
-      -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/include \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/include \
-      -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl \
       -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/awt \
       -I$(JDK_TOPDIR)/src/java.desktop/unix/native/libawt_xawt/awt \
       -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/font \
+      -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
+      -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/include \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/include \
       -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \
       -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d \
       -I$(JDK_TOPDIR)/src/java.desktop/unix/native/libawt/java2d \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libmlib_image/ \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \
       -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \
       -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/awt/debug \
+      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libmlib_image/ \
       -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxapp \
       $(LIBJAVA_HEADER_FLAGS) \
       #
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index 345c425..27dad35 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -33,10 +33,22 @@
 # libfdlibm is statically linked with libjava below and not delivered into the
 # product on its own.
 
-BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+BUILD_LIBFDLIBM_OPTIMIZATION := NONE
 
-ifneq ($(OPENJDK_TARGET_OS), solaris)
-  BUILD_LIBFDLIBM_OPTIMIZATION := NONE
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+  BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+endif
+
+ifeq ($(OPENJDK_TARGET_OS), linux)
+  ifeq ($(OPENJDK_TARGET_CPU), ppc64)
+    BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+  else ifeq ($(OPENJDK_TARGET_CPU), ppc64le)
+    BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+  else ifeq ($(OPENJDK_TARGET_CPU), s390x)
+    BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+  else ifeq ($(OPENJDK_TARGET_CPU), aarch64)
+    BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+  endif
 endif
 
 LIBFDLIBM_SRC := $(JDK_TOPDIR)/src/java.base/share/native/libfdlibm
@@ -51,6 +63,10 @@
       CFLAGS := $(CFLAGS_JDKLIB) $(LIBFDLIBM_CFLAGS), \
       CFLAGS_windows_debug := -DLOGGING, \
       CFLAGS_aix := -qfloat=nomaf, \
+      CFLAGS_linux_ppc64 := -ffp-contract=off, \
+      CFLAGS_linux_ppc64le := -ffp-contract=off, \
+      CFLAGS_linux_s390x := -ffp-contract=off, \
+      CFLAGS_linux_aarch64 := -ffp-contract=off, \
       DISABLED_WARNINGS_gcc := sign-compare, \
       DISABLED_WARNINGS_microsoft := 4146 4244 4018, \
       ARFLAGS := $(ARFLAGS), \
diff --git a/jdk/make/src/classes/build/tools/jigsaw/AddPackagesAttribute.java b/jdk/make/src/classes/build/tools/jigsaw/AddPackagesAttribute.java
index 5d212cd..7aa02f3 100644
--- a/jdk/make/src/classes/build/tools/jigsaw/AddPackagesAttribute.java
+++ b/jdk/make/src/classes/build/tools/jigsaw/AddPackagesAttribute.java
@@ -65,7 +65,7 @@
                     String mn = entry.getFileName().toString();
                     Optional<ModuleReference> omref = finder.find(mn);
                     if (omref.isPresent()) {
-                        Set<String> packages = omref.get().descriptor().conceals();
+                        Set<String> packages = omref.get().descriptor().packages();
                         addPackagesAttribute(mi, packages);
                     }
                 }
@@ -77,7 +77,7 @@
         byte[] bytes;
         try (InputStream in = Files.newInputStream(mi)) {
             ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
-            extender.conceals(packages);
+            extender.packages(packages);
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             extender.write(baos);
             bytes = baos.toByteArray();
diff --git a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
index 04badbd..bf0f03b 100644
--- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
@@ -43,7 +43,7 @@
 import java.util.TreeSet;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import static java.lang.module.ModuleDescriptor.Requires.Modifier.PUBLIC;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.TRANSITIVE;
 
 /**
  * Generate the DOT file for a module graph for each module in the JDK
@@ -172,14 +172,14 @@
             Graph<String> graph = gengraph(cf);
             descriptors.forEach(md -> {
                 String mn = md.name();
-                Set<String> requiresPublic = md.requires().stream()
-                        .filter(d -> d.modifiers().contains(PUBLIC))
+                Set<String> requiresTransitive = md.requires().stream()
+                        .filter(d -> d.modifiers().contains(TRANSITIVE))
                         .map(d -> d.name())
                         .collect(Collectors.toSet());
 
                 graph.adjacentNodes(mn).forEach(dn -> {
                     String attr = dn.equals("java.base") ? REQUIRES_BASE
-                            : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES);
+                            : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
                     int w = weightOf(mn, dn);
                     if (w > 1)
                         attr += "weight=" + w;
@@ -194,8 +194,8 @@
     /**
      * Returns a Graph of the given Configuration after transitive reduction.
      *
-     * Transitive reduction of requires public edge and requires edge have
-     * to be applied separately to prevent the requires public edges
+     * Transitive reduction of requires transitive edge and requires edge have
+     * to be applied separately to prevent the requires transitive edges
      * (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V)
      * in which  V would not be re-exported from U.
      */
@@ -208,21 +208,21 @@
                     .map(ResolvedModule::name)
                     .forEach(target -> builder.addEdge(mn, target));
         }
-        Graph<String> rpg = requiresPublicGraph(cf);
+        Graph<String> rpg = requiresTransitiveGraph(cf);
         return builder.build().reduce(rpg);
     }
 
     /**
-     * Returns a Graph containing only requires public edges
+     * Returns a Graph containing only requires transitive edges
      * with transitive reduction.
      */
-    private Graph<String> requiresPublicGraph(Configuration cf) {
+    private Graph<String> requiresTransitiveGraph(Configuration cf) {
         Graph.Builder<String> builder = new Graph.Builder<>();
         for (ResolvedModule resolvedModule : cf.modules()) {
             ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
             String mn = descriptor.name();
             descriptor.requires().stream()
-                    .filter(d -> d.modifiers().contains(PUBLIC))
+                    .filter(d -> d.modifiers().contains(TRANSITIVE))
                     .map(d -> d.name())
                     .forEach(d -> builder.addEdge(mn, d));
         }
diff --git a/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java b/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java
index 7fb8679..e55a1c0 100644
--- a/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java
+++ b/jdk/make/src/classes/build/tools/jigsaw/ModuleSummary.java
@@ -299,7 +299,7 @@
     static class HtmlDocument {
         final String title;
         final Map<String, ModuleSummary> modules;
-        boolean requiresPublicNote = false;
+        boolean requiresTransitiveNote = false;
         boolean aggregatorNote = false;
         boolean totalBytesNote = false;
         HtmlDocument(String title, Map<String, ModuleSummary> modules) {
@@ -510,16 +510,16 @@
             public String requiresColumn() {
                 StringBuilder sb = new StringBuilder();
                 sb.append(String.format("<td>"));
-                boolean footnote = requiresPublicNote;
+                boolean footnote = requiresTransitiveNote;
                 ms.descriptor().requires().stream()
                         .sorted(Comparator.comparing(Requires::name))
                         .forEach(r -> {
-                            boolean requiresPublic = r.modifiers().contains(Requires.Modifier.PUBLIC);
-                            Selector sel = requiresPublic ? REQUIRES_PUBLIC : REQUIRES;
+                            boolean requiresTransitive = r.modifiers().contains(Requires.Modifier.TRANSITIVE);
+                            Selector sel = requiresTransitive ? REQUIRES_PUBLIC : REQUIRES;
                             String req = String.format("<a class=\"%s\" href=\"#%s\">%s</a>",
                                                        sel, r.name(), r.name());
-                            if (!requiresPublicNote && requiresPublic) {
-                                requiresPublicNote = true;
+                            if (!requiresTransitiveNote && requiresTransitive) {
+                                requiresTransitiveNote = true;
                                 req += "<sup>*</sup>";
                             }
                             sb.append(req).append("\n").append("<br>");
@@ -534,8 +534,8 @@
                     sb.append("<br>");
                     sb.append("<i>+").append(indirectDeps).append(" transitive dependencies</i>");
                 }
-                if (footnote != requiresPublicNote) {
-                    sb.append("<br><br>").append("<i>* bold denotes requires public</i>");
+                if (footnote != requiresTransitiveNote) {
+                    sb.append("<br><br>").append("<i>* bold denotes requires transitive</i>");
                 }
                 sb.append("</td>");
                 return sb.toString();
@@ -558,11 +558,10 @@
                 ms.descriptor().uses().stream()
                         .sorted()
                         .forEach(s -> sb.append("uses ").append(s).append("<br>").append("\n"));
-                ms.descriptor().provides().entrySet().stream()
-                        .sorted(Map.Entry.comparingByKey())
-                        .flatMap(e -> e.getValue().providers().stream()
-                                .map(p -> String.format("provides %s<br>&nbsp;&nbsp;&nbsp;&nbsp;with %s",
-                                                        e.getKey(), p)))
+                ms.descriptor().provides().stream()
+                        .sorted(Comparator.comparing(Provides::service))
+                        .map(p -> String.format("provides %s<br>&nbsp;&nbsp;&nbsp;&nbsp;with %s",
+                                                p.service(), p.providers()))
                         .forEach(p -> sb.append(p).append("<br>").append("\n"));
                 sb.append("</td>");
                 return sb.toString();
diff --git a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java
index e7d932d..60d0b6e 100644
--- a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java
+++ b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java
@@ -30,219 +30,594 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static java.util.stream.Collectors.*;
 
 /**
  * A build tool to extend the module-info.java in the source tree for
- * platform-specific exports, uses, and provides and write to the specified
- * output file. Injecting platform-specific requires is not supported.
+ * platform-specific exports, opens, uses, and provides and write to
+ * the specified output file.
  *
- * The extra exports, uses, provides can be specified in module-info.java.extra
- * files and GenModuleInfoSource will be invoked for each module that has
+ * GenModuleInfoSource will be invoked for each module that has
  * module-info.java.extra in the source directory.
+ *
+ * The extra exports, opens, uses, provides can be specified
+ * in module-info.java.extra.
+ * Injecting platform-specific requires is not supported.
+ *
+ * @see build.tools.module.ModuleInfoExtraTest for basic testing
  */
 public class GenModuleInfoSource {
     private final static String USAGE =
-        "Usage: GenModuleInfoSource [option] -o <output file> <module-info-java>\n" +
-        "Options are:\n" +
-        "  -exports  <package-name>\n" +
-        "  -exports  <package-name>[/<module-name>]\n" +
-        "  -uses     <service>\n" +
-        "  -provides <service>/<provider-impl-classname>\n";
+        "Usage: GenModuleInfoSource -o <output file> \n" +
+        "  --source-file <module-info-java>\n" +
+        "  --modules <module-name>[,<module-name>...]\n" +
+        "  <module-info.java.extra> ...\n";
 
+    static boolean verbose = false;
     public static void main(String... args) throws Exception {
         Path outfile = null;
         Path moduleInfoJava = null;
-        GenModuleInfoSource genModuleInfo = new GenModuleInfoSource();
-
+        Set<String> modules = Collections.emptySet();
+        List<Path> extras = new ArrayList<>();
         // validate input arguments
         for (int i = 0; i < args.length; i++){
             String option = args[i];
-            if (option.startsWith("-")) {
-                String arg = args[++i];
-                if (option.equals("-exports")) {
-                    int index = arg.indexOf('/');
-                        if (index > 0) {
-                            String pn = arg.substring(0, index);
-                            String mn = arg.substring(index + 1, arg.length());
-                            genModuleInfo.exportTo(pn, mn);
-                        } else {
-                            genModuleInfo.export(arg);
-                        }
-                } else if (option.equals("-uses")) {
-                    genModuleInfo.use(arg);
-                } else if (option.equals("-provides")) {
-                        int index = arg.indexOf('/');
-                        if (index <= 0) {
-                            throw new IllegalArgumentException("invalid -provide argument: " + arg);
-                        }
-                        String service = arg.substring(0, index);
-                        String impl = arg.substring(index + 1, arg.length());
-                        genModuleInfo.provide(service, impl);
-                } else if (option.equals("-o")) {
+            String arg = i+1 < args.length ? args[i+1] : null;
+            switch (option) {
+                case "-o":
                     outfile = Paths.get(arg);
-                } else {
-                    throw new IllegalArgumentException("invalid option: " + option);
-                }
-            } else if (moduleInfoJava != null) {
-                throw new IllegalArgumentException("more than one module-info.java");
-            } else {
-                moduleInfoJava = Paths.get(option);
-                if (Files.notExists(moduleInfoJava)) {
-                    throw new IllegalArgumentException(option + " not exist");
-                }
+                    i++;
+                    break;
+                case "--source-file":
+                    moduleInfoJava = Paths.get(arg);
+                    if (Files.notExists(moduleInfoJava)) {
+                        throw new IllegalArgumentException(moduleInfoJava + " not exist");
+                    }
+                    i++;
+                    break;
+                case "--modules":
+                    modules = Arrays.stream(arg.split(","))
+                                    .collect(toSet());
+                    i++;
+                    break;
+                case "-v":
+                    verbose = true;
+                    break;
+                default:
+                    Path file = Paths.get(option);
+                    if (Files.notExists(file)) {
+                        throw new IllegalArgumentException(file + " not exist");
+                    }
+                    extras.add(file);
             }
         }
 
-        if (moduleInfoJava == null || outfile == null) {
+        if (moduleInfoJava == null || outfile == null ||
+                modules.isEmpty() || extras.isEmpty()) {
             System.err.println(USAGE);
             System.exit(-1);
         }
 
+        GenModuleInfoSource genModuleInfo =
+            new GenModuleInfoSource(moduleInfoJava, extras, modules);
+
         // generate new module-info.java
-        genModuleInfo.generate(moduleInfoJava, outfile);
+        genModuleInfo.generate(outfile);
     }
 
-    private final Set<String> exports = new HashSet<>();
-    private final Map<String, Set<String>> exportsTo = new HashMap<>();
-    private final Set<String> uses = new HashSet<>();
-    private final Map<String, Set<String>> provides = new HashMap<>();
-    GenModuleInfoSource() {
-    }
+    final Path sourceFile;
+    final List<Path> extraFiles;
+    final ModuleInfo extras;
+    final Set<String> modules;
+    final ModuleInfo moduleInfo;
+    GenModuleInfoSource(Path sourceFile, List<Path> extraFiles, Set<String> modules)
+        throws IOException
+    {
+        this.sourceFile = sourceFile;
+        this.extraFiles = extraFiles;
+        this.modules = modules;
+        this.moduleInfo = new ModuleInfo();
+        this.moduleInfo.parse(sourceFile);
 
-    private void export(String p) {
-        Objects.requireNonNull(p);
-        if (exports.contains(p) || exportsTo.containsKey(p)) {
-            throw new RuntimeException("duplicated exports: " + p);
+        // parse module-info.java.extra
+        this.extras = new ModuleInfo();
+        for (Path file : extraFiles) {
+            extras.parse(file);
         }
-        exports.add(p);
-    }
-    private void exportTo(String p, String mn) {
-        Objects.requireNonNull(p);
-        Objects.requireNonNull(mn);
-        if (exports.contains(p)) {
-            throw new RuntimeException("unqualified exports already exists: " + p);
-        }
-        exportsTo.computeIfAbsent(p, _k -> new HashSet<>()).add(mn);
+
+        // merge with module-info.java.extra
+        moduleInfo.augmentModuleInfo(extras, modules);
     }
 
-    private void use(String service) {
-        uses.add(service);
-    }
-
-    private void provide(String s, String impl) {
-        provides.computeIfAbsent(s, _k -> new HashSet<>()).add(impl);
-    }
-
-    private void generate(Path sourcefile, Path outfile) throws IOException {
-        Path parent = outfile.getParent();
-        if (parent != null)
-            Files.createDirectories(parent);
-
-        List<String> lines = Files.readAllLines(sourcefile);
-        try (BufferedWriter bw = Files.newBufferedWriter(outfile);
+    void generate(Path output) throws IOException {
+        List<String> lines = Files.readAllLines(sourceFile);
+        try (BufferedWriter bw = Files.newBufferedWriter(output);
              PrintWriter writer = new PrintWriter(bw)) {
-            int lineNumber = 0;
+            // write the copyright header and lines up to module declaration
             for (String l : lines) {
-                lineNumber++;
-                String[] s = l.trim().split("\\s+");
-                String keyword = s[0].trim();
-                int nextIndex = keyword.length();
-                String exp = null;
-                int n = l.length();
-                switch (keyword) {
-                    case "exports":
-                        boolean inExportsTo = false;
-                        // assume package name immediately after exports
-                        exp = s[1].trim();
-                        if (s.length >= 3) {
-                            nextIndex = l.indexOf(exp, nextIndex) + exp.length();
-                            if (s[2].trim().equals("to")) {
-                                inExportsTo = true;
-                                n = l.indexOf("to", nextIndex) + "to".length();
-                            } else {
-                                throw new RuntimeException(sourcefile + ", line " +
-                                    lineNumber + ", is malformed: " + s[2]);
-                            }
-                        }
-
-                        // inject the extra targets after "to"
-                        if (inExportsTo) {
-                            writer.println(injectExportTargets(exp, l, n));
-                        } else {
-                            writer.println(l);
-                        }
-                        break;
-                    case "to":
-                        if (exp == null) {
-                            throw new RuntimeException(sourcefile + ", line " +
-                                lineNumber + ", is malformed");
-                        }
-                        n = l.indexOf("to", nextIndex) + "to".length();
-                        writer.println(injectExportTargets(exp, l, n));
-                        break;
-                    case "}":
-                        doAugments(writer);
-                        // fall through
-                    default:
-                        writer.println(l);
-                        // reset exports
-                        exp = null;
+                writer.println(l);
+                if (l.trim().startsWith("module ")) {
+                    // print URI rather than file path to avoid escape
+                    writer.format("    // source file: %s%n", sourceFile.toUri());
+                    for (Path file: extraFiles) {
+                        writer.format("    //              %s%n", file.toUri());
+                    }
+                    break;
                 }
             }
+
+            // requires
+            for (String l : lines) {
+                if (l.trim().startsWith("requires"))
+                    writer.println(l);
+            }
+
+            // write exports, opens, uses, and provides
+            moduleInfo.print(writer);
+
+            // close
+            writer.println("}");
         }
     }
 
-    private String injectExportTargets(String pn, String exp, int pos) {
-        Set<String> targets = exportsTo.remove(pn);
-        if (targets != null) {
-            StringBuilder sb = new StringBuilder();
-            // inject the extra targets after the given pos
-            sb.append(exp.substring(0, pos))
-              .append("\n\t")
-              .append(targets.stream()
-                             .collect(Collectors.joining(",", "", ",")))
-              .append(" /* injected */");
-            if (pos < exp.length()) {
-                // print the remaining statement followed "to"
-                sb.append("\n\t")
-                  .append(exp.substring(pos+1, exp.length()));
+
+    class ModuleInfo {
+        final Map<String, Statement> exports = new HashMap<>();
+        final Map<String, Statement> opens = new HashMap<>();
+        final Map<String, Statement> uses = new HashMap<>();
+        final Map<String, Statement> provides = new HashMap<>();
+
+        Statement getStatement(String directive, String name) {
+            switch (directive) {
+                case "exports":
+                    if (moduleInfo.exports.containsKey(name) &&
+                        moduleInfo.exports.get(name).isUnqualified()) {
+                        throw new IllegalArgumentException(sourceFile +
+                            " already has " + directive + " " + name);
+                    }
+                    return exports.computeIfAbsent(name,
+                        _n -> new Statement("exports", "to", name));
+
+                case "opens":
+                    if (moduleInfo.opens.containsKey(name) &&
+                        moduleInfo.opens.get(name).isUnqualified()) {
+                        throw new IllegalArgumentException(sourceFile +
+                            " already has " + directive + " " + name);
+                    }
+
+                    if (moduleInfo.opens.containsKey(name)) {
+                        throw new IllegalArgumentException(sourceFile +
+                            " already has " + directive + " " + name);
+                    }
+                    return opens.computeIfAbsent(name,
+                        _n -> new Statement("opens", "to", name));
+
+                case "uses":
+                    return uses.computeIfAbsent(name,
+                        _n -> new Statement("uses", "", name));
+
+                case "provides":
+                    return provides.computeIfAbsent(name,
+                        _n -> new Statement("provides", "with", name, true));
+
+                default:
+                    throw new IllegalArgumentException(directive);
+            }
+
+        }
+
+        /*
+         * Augment this ModuleInfo with module-info.java.extra
+         */
+        void augmentModuleInfo(ModuleInfo extraFiles, Set<String> modules) {
+            // API package exported in the original module-info.java
+            extraFiles.exports.entrySet()
+                .stream()
+                .filter(e -> exports.containsKey(e.getKey()) &&
+                                e.getValue().filter(modules))
+                .forEach(e -> mergeExportsOrOpens(exports.get(e.getKey()),
+                                                  e.getValue(),
+                                                  modules));
+
+            // add exports that are not defined in the original module-info.java
+            extraFiles.exports.entrySet()
+                .stream()
+                .filter(e -> !exports.containsKey(e.getKey()) &&
+                                e.getValue().filter(modules))
+                .forEach(e -> addTargets(getStatement("exports", e.getKey()),
+                                         e.getValue(),
+                                         modules));
+
+            // API package opened in the original module-info.java
+            extraFiles.opens.entrySet()
+                .stream()
+                .filter(e -> opens.containsKey(e.getKey()) &&
+                                e.getValue().filter(modules))
+                .forEach(e -> mergeExportsOrOpens(opens.get(e.getKey()),
+                                                  e.getValue(),
+                                                  modules));
+
+            // add opens that are not defined in the original module-info.java
+            extraFiles.opens.entrySet()
+                .stream()
+                .filter(e -> !opens.containsKey(e.getKey()) &&
+                                e.getValue().filter(modules))
+                .forEach(e -> addTargets(getStatement("opens", e.getKey()),
+                                         e.getValue(),
+                                         modules));
+
+            // provides
+            extraFiles.provides.keySet()
+                .stream()
+                .filter(service -> provides.containsKey(service))
+                .forEach(service -> mergeProvides(service,
+                                                  extraFiles.provides.get(service)));
+            extraFiles.provides.keySet()
+                .stream()
+                .filter(service -> !provides.containsKey(service))
+                .forEach(service -> provides.put(service,
+                                                 extraFiles.provides.get(service)));
+
+            // uses
+            extraFiles.uses.keySet()
+                .stream()
+                .filter(service -> !uses.containsKey(service))
+                .forEach(service -> uses.put(service, extraFiles.uses.get(service)));
+        }
+
+        // add qualified exports or opens to known modules only
+        private void addTargets(Statement statement,
+                                Statement extra,
+                                Set<String> modules)
+        {
+            extra.targets.stream()
+                 .filter(mn -> modules.contains(mn))
+                 .forEach(mn -> statement.addTarget(mn));
+        }
+
+        private void mergeExportsOrOpens(Statement statement,
+                                         Statement extra,
+                                         Set<String> modules)
+        {
+            String pn = statement.name;
+            if (statement.isUnqualified() && extra.isQualified()) {
+                throw new RuntimeException("can't add qualified exports to " +
+                    "unqualified exports " + pn);
+            }
+
+            Set<String> mods = extra.targets.stream()
+                .filter(mn -> statement.targets.contains(mn))
+                .collect(toSet());
+            if (mods.size() > 0) {
+                throw new RuntimeException("qualified exports " + pn + " to " +
+                    mods.toString() + " already declared in " + sourceFile);
+            }
+
+            // add qualified exports or opens to known modules only
+            addTargets(statement, extra, modules);
+        }
+
+        private void mergeProvides(String service, Statement extra) {
+            Statement statement = provides.get(service);
+
+            Set<String> mods = extra.targets.stream()
+                .filter(mn -> statement.targets.contains(mn))
+                .collect(toSet());
+
+            if (mods.size() > 0) {
+                throw new RuntimeException("qualified exports " + service + " to " +
+                    mods.toString() + " already declared in " + sourceFile);
+            }
+
+            extra.targets.stream()
+                 .forEach(mn -> statement.addTarget(mn));
+        }
+
+
+        void print(PrintWriter writer) {
+            // print unqualified exports
+            exports.entrySet().stream()
+                .filter(e -> e.getValue().targets.isEmpty())
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> writer.println(e.getValue()));
+
+            // print qualified exports
+            exports.entrySet().stream()
+                .filter(e -> !e.getValue().targets.isEmpty())
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> writer.println(e.getValue()));
+
+            // print unqualified opens
+            opens.entrySet().stream()
+                .filter(e -> e.getValue().targets.isEmpty())
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> writer.println(e.getValue()));
+
+            // print qualified opens
+            opens.entrySet().stream()
+                .filter(e -> !e.getValue().targets.isEmpty())
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> writer.println(e.getValue()));
+
+            // uses and provides
+            writer.println();
+            uses.entrySet().stream()
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> writer.println(e.getValue()));
+            provides.entrySet().stream()
+                .sorted(Map.Entry.comparingByKey())
+                .forEach(e -> writer.println(e.getValue()));
+        }
+
+        private void parse(Path sourcefile) throws IOException {
+            List<String> lines = Files.readAllLines(sourcefile);
+            Statement statement = null;
+            boolean hasTargets = false;
+
+            for (int lineNumber = 1; lineNumber <= lines.size(); ) {
+                String l = lines.get(lineNumber-1).trim();
+                int index = 0;
+
+                if (l.isEmpty()) {
+                    lineNumber++;
+                    continue;
+                }
+
+                // comment block starts
+                if (l.startsWith("/*")) {
+                    while (l.indexOf("*/") == -1) { // end comment block
+                        l = lines.get(lineNumber++).trim();
+                    }
+                    index = l.indexOf("*/") + 2;
+                    if (index >= l.length()) {
+                        lineNumber++;
+                        continue;
+                    } else {
+                        // rest of the line
+                        l = l.substring(index, l.length()).trim();
+                        index = 0;
+                    }
+                }
+
+                // skip comment and annotations
+                if (l.startsWith("//") || l.startsWith("@")) {
+                    lineNumber++;
+                    continue;
+                }
+
+                int current = lineNumber;
+                int count = 0;
+                while (index < l.length()) {
+                    if (current == lineNumber && ++count > 20)
+                        throw new Error("Fail to parse line " + lineNumber + " " + sourcefile);
+
+                    int end = l.indexOf(';');
+                    if (end == -1)
+                        end = l.length();
+                    String content = l.substring(0, end).trim();
+                    if (content.isEmpty()) {
+                        index = end+1;
+                        if (index < l.length()) {
+                            // rest of the line
+                            l = l.substring(index, l.length()).trim();
+                            index = 0;
+                        }
+                        continue;
+                    }
+
+                    String[] s = content.split("\\s+");
+                    String keyword = s[0].trim();
+
+                    String name = s.length > 1 ? s[1].trim() : null;
+                    trace("%d: %s index=%d len=%d%n", lineNumber, l, index, l.length());
+                    switch (keyword) {
+                        case "module":
+                        case "requires":
+                        case "}":
+                            index = l.length();  // skip to the end
+                            continue;
+
+                        case "exports":
+                        case "opens":
+                        case "provides":
+                        case "uses":
+                            // assume name immediately after exports, opens, provides, uses
+                            statement = getStatement(keyword, name);
+                            hasTargets = false;
+
+                            int i = l.indexOf(name, keyword.length()+1) + name.length() + 1;
+                            l = i < l.length() ? l.substring(i, l.length()).trim() : "";
+                            index = 0;
+
+                            if (s.length >= 3) {
+                                if (!s[2].trim().equals(statement.qualifier)) {
+                                    throw new RuntimeException(sourcefile + ", line " +
+                                        lineNumber + ", is malformed: " + s[2]);
+                                }
+                            }
+
+                            break;
+
+                        case "to":
+                        case "with":
+                            if (statement == null) {
+                                throw new RuntimeException(sourcefile + ", line " +
+                                    lineNumber + ", is malformed");
+                            }
+
+                            hasTargets = true;
+                            String qualifier = statement.qualifier;
+                            i = l.indexOf(qualifier, index) + qualifier.length() + 1;
+                            l = i < l.length() ? l.substring(i, l.length()).trim() : "";
+                            index = 0;
+                            break;
+                    }
+
+                    if (index >= l.length()) {
+                        // skip to next line
+                        continue;
+                    }
+
+                        // comment block starts
+                    if (l.startsWith("/*")) {
+                        while (l.indexOf("*/") == -1) { // end comment block
+                            l = lines.get(lineNumber++).trim();
+                        }
+                        index = l.indexOf("*/") + 2;
+                        if (index >= l.length()) {
+                            continue;
+                        } else {
+                            // rest of the line
+                            l = l.substring(index, l.length()).trim();
+                            index = 0;
+                        }
+                    }
+
+                    if (l.startsWith("//")) {
+                        index = l.length();
+                        continue;
+                    }
+
+                    if (statement == null) {
+                        throw new RuntimeException(sourcefile + ", line " +
+                            lineNumber + ": missing keyword?");
+                    }
+
+                    if (!hasTargets) {
+                        continue;
+                    }
+
+                    if (index >= l.length()) {
+                        throw new RuntimeException(sourcefile + ", line " +
+                            lineNumber + ": " + l);
+                    }
+
+                    // parse the target module of exports, opens, or provides
+                    Statement stmt = statement;
+
+                    int terminal = l.indexOf(';', index);
+                    // determine up to which position to parse
+                    int pos = terminal != -1 ? terminal : l.length();
+                    // parse up to comments
+                    int pos1 = l.indexOf("//", index);
+                    if (pos1 != -1 && pos1 < pos) {
+                        pos = pos1;
+                    }
+                    int pos2 = l.indexOf("/*", index);
+                    if (pos2 != -1 && pos2 < pos) {
+                        pos = pos2;
+                    }
+                    // target module(s) for qualitifed exports or opens
+                    // or provider implementation class(es)
+                    String rhs = l.substring(index, pos).trim();
+                    index += rhs.length();
+                    trace("rhs: index=%d [%s] [line: %s]%n", index, rhs, l);
+
+                    String[] targets = rhs.split(",");
+                    for (String t : targets) {
+                        String n = t.trim();
+                        if (n.length() > 0)
+                            stmt.addTarget(n);
+                    }
+
+                    // start next statement
+                    if (pos == terminal) {
+                        statement = null;
+                        hasTargets = false;
+                        index = terminal + 1;
+                    }
+                    l = index < l.length() ? l.substring(index, l.length()).trim() : "";
+                    index = 0;
+                }
+
+                lineNumber++;
+            }
+        }
+    }
+
+    static class Statement {
+        final String directive;
+        final String qualifier;
+        final String name;
+        final Set<String> targets = new LinkedHashSet<>();
+        final boolean ordered;
+
+        Statement(String directive, String qualifier, String name) {
+            this(directive, qualifier, name, false);
+        }
+
+        Statement(String directive, String qualifier, String name, boolean ordered) {
+            this.directive = directive;
+            this.qualifier = qualifier;
+            this.name = name;
+            this.ordered = ordered;
+        }
+
+        Statement addTarget(String mn) {
+            if (mn.isEmpty())
+                throw new IllegalArgumentException("empty module name");
+            targets.add(mn);
+            return this;
+        }
+
+        boolean isQualified() {
+            return targets.size() > 0;
+        }
+
+        boolean isUnqualified() {
+            return targets.isEmpty();
+        }
+
+        /**
+         * Returns true if this statement is unqualified or it has
+         * at least one target in the given names.
+         */
+        boolean filter(Set<String> names) {
+            if (isUnqualified()) {
+                return true;
+            } else {
+                return targets.stream()
+                    .filter(mn -> names.contains(mn))
+                    .findAny().isPresent();
+            }
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder("    ");
+            sb.append(directive).append(" ").append(name);
+            if (targets.isEmpty()) {
+                sb.append(";");
+            } else if (targets.size() == 1) {
+                sb.append(" ").append(qualifier)
+                  .append(orderedTargets().collect(joining(",", " ", ";")));
+            } else {
+                sb.append(" ").append(qualifier)
+                  .append(orderedTargets()
+                      .map(target -> String.format("        %s", target))
+                      .collect(joining(",\n", "\n", ";")));
             }
             return sb.toString();
-        } else {
-            return exp;
+        }
+
+        public Stream<String> orderedTargets() {
+            return ordered ? targets.stream()
+                           : targets.stream().sorted();
         }
     }
 
-    private void doAugments(PrintWriter writer) {
-        if ((exports.size() + exportsTo.size() + uses.size() + provides.size()) == 0)
-            return;
-
-        writer.println("    // augmented from module-info.java.extra");
-        exports.stream()
-            .sorted()
-            .forEach(e -> writer.format("    exports %s;%n", e));
-        // remaining injected qualified exports
-        exportsTo.entrySet().stream()
-            .sorted(Map.Entry.comparingByKey())
-            .map(e -> String.format("    exports %s to%n%s;", e.getKey(),
-                                    e.getValue().stream().sorted()
-                                        .map(mn -> String.format("        %s", mn))
-                                        .collect(Collectors.joining(",\n"))))
-            .forEach(writer::println);
-        uses.stream().sorted()
-            .forEach(s -> writer.format("    uses %s;%n", s));
-        provides.entrySet().stream()
-            .sorted(Map.Entry.comparingByKey())
-            .flatMap(e -> e.getValue().stream().sorted()
-                           .map(impl -> String.format("    provides %s with %s;",
-                                                      e.getKey(), impl)))
-            .forEach(writer::println);
+    static void trace(String fmt, Object... params) {
+        if (verbose) {
+            System.out.format(fmt, params);
+        }
     }
 }
diff --git a/jdk/make/src/classes/build/tools/module/ModuleInfoExtraTest.java b/jdk/make/src/classes/build/tools/module/ModuleInfoExtraTest.java
new file mode 100644
index 0000000..5554c71
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/module/ModuleInfoExtraTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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 build.tools.module;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import build.tools.module.GenModuleInfoSource.Statement;
+
+/**
+ * Sanity test for GenModuleInfoSource tool
+ */
+public class ModuleInfoExtraTest {
+    private static final Path DIR = Paths.get("test");
+    public static void main(String... args) throws Exception {
+        if (args.length != 0)
+            GenModuleInfoSource.verbose = true;
+
+        ModuleInfoExtraTest test = new ModuleInfoExtraTest("m", "m1", "m2", "m3");
+        test.run();
+    }
+
+    String[] moduleInfo = new String[] {
+        "exports p",
+        "to",
+        "   // comment",
+        "   /* comment */ m1",
+        ",",
+        "m2,m3",
+        "   ;",
+        "exports q to m1;",
+        "provides s with /* ",
+        "  comment */ impl     ;    // comment",
+        "provides s1",
+        "    with  ",
+        "    impl1, impl2;"
+    };
+
+    String[] moduleInfoExtra = new String[] {
+        "exports q",
+        "to",
+        "   m2 // comment",
+        "   /* comment */;",
+        "   ;",
+        "opens p.q ",
+        "   to /* comment */ m3",
+        "   , // m1",
+        "   /* comment */, m4;",
+        "provides s1 with impl3;"
+    };
+
+    String[] test1 = new String[] {
+        "exports p1 to m1;",
+        "exports p2"
+    };
+
+    String[] test2 = new String[] {
+        "exports to m1;"
+    };
+
+    String[] test3 = new String[]{
+        "exports p3 to m1;",
+        "    m2, m3;"
+    };
+
+    String[] test4 = new String[]{
+        "provides s with impl1;",   // typo ; should be ,
+        "   impl2, impl3;"
+    };
+
+    String[] test5 = new String[]{
+        "uses s3",
+        "provides s3 with impl1,",
+        "   impl2, impl3;"
+    };
+
+    final Builder builder;
+    ModuleInfoExtraTest(String name, String... modules) {
+        this.builder = new Builder(name).modules(modules);
+    }
+
+    void run() throws IOException {
+        testModuleInfo();
+        errorCases();
+    }
+
+
+    void testModuleInfo() throws IOException {
+        GenModuleInfoSource source = builder.sourceFile(moduleInfo).build();
+        Set<String> targetsP = new HashSet<>();
+        targetsP.add("m1");
+        targetsP.add("m2");
+        targetsP.add("m3");
+
+        Set<String> targetsQ = new HashSet<>();
+        targetsQ.add("m1");
+
+        Set<String> providerS = new HashSet<>();
+        providerS.add("impl");
+
+        Set<String> providerS1 = new HashSet<>();
+        providerS1.add("impl1");
+        providerS1.add("impl2");
+
+        Set<String> opensPQ = new HashSet<>();
+
+        check(source, targetsP, targetsQ, opensPQ, providerS, providerS1);
+
+        // augment with extra
+        Path file = DIR.resolve("extra");
+        Files.write(file, Arrays.asList(moduleInfoExtra));
+        source = builder.build(file);
+
+        targetsQ.add("m2");
+        providerS1.add("impl3");
+
+        opensPQ.add("m3");
+        check(source, targetsP, targetsQ, opensPQ, providerS, providerS1);
+    }
+
+    void check(GenModuleInfoSource source,
+               Set<String> targetsP,
+               Set<String> targetsQ,
+               Set<String> opensPQ,
+               Set<String> providerS,
+               Set<String> providerS1) {
+        source.moduleInfo.print(new PrintWriter(System.out, true));
+        Statement export = source.moduleInfo.exports.get("p");
+        if (!export.targets.equals(targetsP)) {
+            throw new Error("unexpected: " + export);
+        }
+
+        export = source.moduleInfo.exports.get("q");
+        if (!export.targets.equals(targetsQ)) {
+            throw new Error("unexpected: " + export);
+        }
+
+        Statement provides = source.moduleInfo.provides.get("s");
+        if (!provides.targets.equals(providerS)) {
+            throw new Error("unexpected: " + provides);
+        }
+
+        provides = source.moduleInfo.provides.get("s1");
+        if (!provides.targets.equals(providerS1)) {
+            throw new Error("unexpected: " + provides);
+        }
+    }
+
+
+
+    void errorCases() throws IOException {
+        fail(test1);
+        fail(test2);
+        fail(test3);
+        fail(test4);
+        fail(test5);
+    }
+
+    void fail(String... extras) throws IOException {
+        Path file = DIR.resolve("test1");
+        Files.write(file, Arrays.asList(extras));
+        try {
+            builder.build(file);
+        } catch (RuntimeException e) {
+            if (!e.getMessage().matches("test/test1, line .* is malformed.*") &&
+                !e.getMessage().matches("test/test1, line .* missing keyword.*")) {
+                throw e;
+            }
+        }
+    }
+
+    static class Builder {
+        final String moduleName;
+        final Path sourceFile;
+        final Set<String> modules = new HashSet<>();
+        public Builder(String name) {
+            this.moduleName = name;
+            this.sourceFile = DIR.resolve(name).resolve("module-info.java");
+        }
+
+        public Builder modules(String... names) {
+            Arrays.stream(names).forEach(modules::add);
+            return this;
+        }
+
+        public Builder sourceFile(String... lines) throws IOException {
+            Files.createDirectories(sourceFile.getParent());
+            try (BufferedWriter bw = Files.newBufferedWriter(sourceFile);
+                 PrintWriter writer = new PrintWriter(bw)) {
+                writer.format("module %s {%n", moduleName);
+                for (String l : lines) {
+                    writer.println(l);
+                }
+                writer.println("}");
+            }
+            return this;
+        }
+
+        public GenModuleInfoSource build() throws IOException {
+            return build(Collections.emptyList());
+        }
+
+        public GenModuleInfoSource build(Path extraFile) throws IOException {
+            return build(Collections.singletonList(extraFile));
+        }
+
+        public GenModuleInfoSource build(List<Path> extraFiles) throws IOException {
+            return new GenModuleInfoSource(sourceFile, extraFiles, modules);
+        }
+    }
+
+}
diff --git a/jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
index 9fbf1f0..a3b91bd 100644
--- a/jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
+++ b/jdk/src/java.base/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,7 @@
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.TimeZoneNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -147,6 +148,165 @@
         return Locale.forLanguageTag(langTag);
     }
 
+    public static JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
+        return new JavaTimeDateTimePatternProvider() {
+            @Override
+            public Locale[] getAvailableLocales() {
+                return getSupportedCalendarLocales();
+            }
+
+            @Override
+            public boolean isSupportedLocale(Locale locale) {
+                return isSupportedCalendarLocale(locale);
+            }
+
+            @Override
+            public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) {
+                return toJavaTimeDateTimePattern(calType, getDateTimePattern(dateStyle, timeStyle, locale));
+
+            }
+
+            private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
+                AtomicReferenceArray<String> dateFormatPatterns;
+                SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);
+
+                if (ref == null || (dateFormatPatterns = ref.get()) == null) {
+                    dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);
+                    ref = new SoftReference<>(dateFormatPatterns);
+                    dateFormatPatternsMap.put(locale, ref);
+                }
+                int index = (dateStyle + 1) * 5 + timeStyle + 1;
+                String pattern = dateFormatPatterns.get(index);
+                if (pattern == null) {
+                    String langTag = locale.toLanguageTag();
+                    pattern = translateDateFormatLetters(getCalendarID(langTag),
+                            getDateTimePatternNative(dateStyle, timeStyle, langTag));
+                    if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {
+                        pattern = dateFormatPatterns.get(index);
+                    }
+                }
+                return pattern;
+            }
+
+            /**
+             * This method will convert JRE Date/time Pattern String to JSR310
+             * type Date/Time Pattern
+             */
+            private String toJavaTimeDateTimePattern(String calendarType, String jrePattern) {
+                int length = jrePattern.length();
+                StringBuilder sb = new StringBuilder(length);
+                boolean inQuote = false;
+                int count = 0;
+                char lastLetter = 0;
+                for (int i = 0; i < length; i++) {
+                    char c = jrePattern.charAt(i);
+                    if (c == '\'') {
+                        // '' is treated as a single quote regardless of being
+                        // in a quoted section.
+                        if ((i + 1) < length) {
+                            char nextc = jrePattern.charAt(i + 1);
+                            if (nextc == '\'') {
+                                i++;
+                                if (count != 0) {
+                                    convert(calendarType, lastLetter, count, sb);
+                                    lastLetter = 0;
+                                    count = 0;
+                                }
+                                sb.append("''");
+                                continue;
+                            }
+                        }
+                        if (!inQuote) {
+                            if (count != 0) {
+                                convert(calendarType, lastLetter, count, sb);
+                                lastLetter = 0;
+                                count = 0;
+                            }
+                            inQuote = true;
+                        } else {
+                            inQuote = false;
+                        }
+                        sb.append(c);
+                        continue;
+                    }
+                    if (inQuote) {
+                        sb.append(c);
+                        continue;
+                    }
+                    if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
+                        if (count != 0) {
+                            convert(calendarType, lastLetter, count, sb);
+                            lastLetter = 0;
+                            count = 0;
+                        }
+                        sb.append(c);
+                        continue;
+                    }
+                    if (lastLetter == 0 || lastLetter == c) {
+                        lastLetter = c;
+                        count++;
+                        continue;
+                    }
+                    convert(calendarType, lastLetter, count, sb);
+                    lastLetter = c;
+                    count = 1;
+                }
+                if (inQuote) {
+                    // should not come here.
+                    // returning null so that FALLBACK provider will kick in.
+                    return null;
+                }
+                if (count != 0) {
+                    convert(calendarType, lastLetter, count, sb);
+                }
+                return sb.toString();
+            }
+
+            private void convert(String calendarType, char letter, int count, StringBuilder sb) {
+                switch (letter) {
+                    case 'G':
+                        if (calendarType.equals("japanese")) {
+                            if (count >= 4) {
+                                count = 1;
+                            } else {
+                                count = 5;
+                            }
+                        } else if (!calendarType.equals("iso8601")) {
+                            // Gregorian calendar is iso8601 for java.time
+                            // Adjust the number of 'G's
+                            if (count >= 4) {
+                                // JRE full -> JavaTime full
+                                count = 4;
+                            } else {
+                                // JRE short -> JavaTime short
+                                count = 1;
+                            }
+                        }
+                        break;
+                    case 'y':
+                        if (calendarType.equals("japanese") && count >= 4) {
+                            // JRE specific "gan-nen" support
+                            count = 1;
+                        }
+                        break;
+                    default:
+                        // JSR 310 and CLDR define 5-letter patterns for narrow text.
+                        if (count > 4) {
+                            count = 4;
+                        }
+                        break;
+                }
+                appendN(letter, count, sb);
+            }
+
+            private void appendN(char c, int n, StringBuilder sb) {
+                for (int i = 0; i < n; i++) {
+                    sb.append(c);
+                }
+            }
+        };
+    }
+
     public static DateFormatProvider getDateFormatProvider() {
         return new DateFormatProvider() {
 
@@ -163,20 +323,20 @@
             @Override
             public DateFormat getDateInstance(int style, Locale locale) {
                 return new SimpleDateFormat(getDateTimePattern(style, -1, locale),
-                                            getCalendarLocale(locale));
+                        getCalendarLocale(locale));
             }
 
             @Override
             public DateFormat getTimeInstance(int style, Locale locale) {
                 return new SimpleDateFormat(getDateTimePattern(-1, style, locale),
-                                            getCalendarLocale(locale));
+                        getCalendarLocale(locale));
             }
 
             @Override
             public DateFormat getDateTimeInstance(int dateStyle,
                     int timeStyle, Locale locale) {
                 return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale),
-                                            getCalendarLocale(locale));
+                        getCalendarLocale(locale));
             }
 
             private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
diff --git a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties
index fa9ba74..14bc2ad 100644
--- a/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties
+++ b/jdk/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties
@@ -15,12 +15,12 @@
 pack.class.attribute.CompilationID = RUH
 
 # Module attributes, supported by the tool and not JSR-200
-pack.class.attribute.Module = NH[RUHFH]NH[RUHNH[RUH]]NH[RCH]NH[RCHRCH]
-pack.class.attribute.ConcealedPackages = NH[RUH]
-pack.class.attribute.Version = RUH
-pack.class.attribute.MainClass = RCH
-pack.class.attribute.TargetPlatform = RUHRUHRUH
-pack.class.attribute.Hashes = RUHNH[RUHRUH]
+pack.class.attribute.Module = RUHFHNH[RUHFH]NH[RUHFHNH[RUH]]NH[RUHFHNH[RUH]]NH[RCH]NH[RCHNH[RCH]]
+pack.class.attribute.ModulePackages = NH[RUH]
+pack.class.attribute.ModuleVersion = RUH
+pack.class.attribute.ModuleMainClass = RCH
+pack.class.attribute.ModuleTarget = RUHRUHRUH
+pack.class.attribute.ModuleHashes = RUHNH[RUHNH[B]]
 
 
 # Note:  Zero-length ("marker") attributes do not need to be specified here.
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
index 09b1060..7ae757f 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
@@ -39,6 +39,7 @@
 import java.net.Proxy;
 import java.net.ProtocolException;
 import java.io.*;
+import java.net.Authenticator;
 import javax.net.ssl.*;
 import java.security.Permission;
 import java.util.Map;
@@ -489,4 +490,9 @@
     public void setChunkedStreamingMode (int chunklen) {
         delegate.setChunkedStreamingMode(chunklen);
     }
+
+    @Override
+    public void setAuthenticator(Authenticator auth) {
+        delegate.setAuthenticator(auth);
+    }
 }
diff --git a/jdk/src/java.base/share/classes/java/io/FilePermission.java b/jdk/src/java.base/share/classes/java/io/FilePermission.java
index 0c5c0ac..c3d5113 100644
--- a/jdk/src/java.base/share/classes/java/io/FilePermission.java
+++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java
@@ -216,19 +216,28 @@
             GetPropertyAction.privilegedGetProperty("user.dir"));
 
     /**
-     * A private constructor like a clone, only npath2 is not touched.
+     * A private constructor that clones some and updates some,
+     * always with a different name.
      * @param input
      */
-    private FilePermission(String name, FilePermission input) {
+    private FilePermission(String name,
+                           FilePermission input,
+                           Path npath,
+                           Path npath2,
+                           int mask,
+                           String actions) {
         super(name);
-        this.npath = input.npath;
-        this.actions = input.actions;
+        // Customizables
+        this.npath = npath;
+        this.npath2 = npath2;
+        this.actions = actions;
+        this.mask = mask;
+        // Cloneds
         this.allFiles = input.allFiles;
         this.invalid = input.invalid;
         this.recursive = input.recursive;
         this.directory = input.directory;
         this.cpath = input.cpath;
-        this.mask = input.mask;
     }
 
     /**
@@ -261,10 +270,12 @@
                             // different than the original so that when one is
                             // added to a FilePermissionCollection it will not
                             // be merged with the original one.
-                            FilePermission np = new FilePermission(
-                                    input.getName()+"#plus", input);
-                            np.npath2 = npath2;
-                            return np;
+                            return new FilePermission(input.getName() + "#plus",
+                                    input,
+                                    input.npath,
+                                    npath2,
+                                    input.mask,
+                                    input.actions);
                         }
                     }
                     return input;
@@ -274,10 +285,12 @@
                         Path npath2 = altPath(input.npath);
                         if (npath2 != null) {
                             // New name, see above.
-                            FilePermission np = new FilePermission(
-                                    input.getName()+"#using", input);
-                            np.npath = npath2;
-                            return np;
+                            return new FilePermission(input.getName() + "#using",
+                                    input,
+                                    npath2,
+                                    null,
+                                    input.mask,
+                                    input.actions);
                         }
                     }
                     return null;
@@ -981,6 +994,20 @@
         s.defaultReadObject();
         init(getMask(actions));
     }
+
+    /**
+     * Create a cloned FilePermission with a different actions.
+     * @param effective the new actions
+     * @return a new object
+     */
+    FilePermission withNewActions(int effective) {
+        return new FilePermission(this.getName(),
+                this,
+                this.npath,
+                this.npath2,
+                effective,
+                null);
+    }
 }
 
 /**
@@ -1048,8 +1075,7 @@
         FilePermission fp = (FilePermission)permission;
 
         // Add permission to map if it is absent, or replace with new
-        // permission if applicable. NOTE: cannot use lambda for
-        // remappingFunction parameter until JDK-8076596 is fixed.
+        // permission if applicable.
         perms.merge(fp.getName(), fp,
             new java.util.function.BiFunction<>() {
                 @Override
@@ -1063,7 +1089,8 @@
                             return newVal;
                         }
                         if (effective != oldMask) {
-                            return new FilePermission(fp.getName(), effective);
+                            return ((FilePermission)newVal)
+                                    .withNewActions(effective);
                         }
                     }
                     return existingVal;
diff --git a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
index 2aa9ff3..f9c8eea 100644
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
@@ -1553,13 +1553,20 @@
      */
     @Override
     public IntStream chars() {
-        byte[] val = this.value; int count = this.count; byte coder = this.coder;
-        checkOffset(count, val.length >> coder);
         // Reuse String-based spliterator. This requires a supplier to
         // capture the value and count when the terminal operation is executed
         return StreamSupport.intStream(
-                () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
-                                      : new StringUTF16.CharsSpliterator(val, 0, count, 0),
+                () -> {
+                    // The combined set of field reads are not atomic and thread
+                    // safe but bounds checks will ensure no unsafe reads from
+                    // the byte array
+                    byte[] val = this.value;
+                    int count = this.count;
+                    byte coder = this.coder;
+                    return coder == LATIN1
+                           ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
+                           : new StringUTF16.CharsSpliterator(val, 0, count, 0);
+                },
                 Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
                 false);
     }
@@ -1570,13 +1577,20 @@
      */
     @Override
     public IntStream codePoints() {
-        byte[] val = this.value; int count = this.count; byte coder = this.coder;
-        checkOffset(count, val.length >> coder);
         // Reuse String-based spliterator. This requires a supplier to
         // capture the value and count when the terminal operation is executed
         return StreamSupport.intStream(
-                () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
-                                      : new StringUTF16.CodePointsSpliterator(val, 0, count, 0),
+                () -> {
+                    // The combined set of field reads are not atomic and thread
+                    // safe but bounds checks will ensure no unsafe reads from
+                    // the byte array
+                    byte[] val = this.value;
+                    int count = this.count;
+                    byte coder = this.coder;
+                    return coder == LATIN1
+                           ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
+                           : new StringUTF16.CodePointsSpliterator(val, 0, count, 0);
+                },
                 Spliterator.ORDERED,
                 false);
     }
diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java
index 36d4587..08e1986 100644
--- a/jdk/src/java.base/share/classes/java/lang/Class.java
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java
@@ -26,46 +26,55 @@
 package java.lang;
 
 import java.lang.annotation.Annotation;
+import java.lang.module.ModuleDescriptor.Version;
+import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Array;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.GenericDeclaration;
-import java.lang.reflect.Member;
-import java.lang.reflect.Field;
-import java.lang.reflect.Executable;
-import java.lang.reflect.Method;
-import java.lang.reflect.Module;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.Proxy;
 import java.lang.ref.SoftReference;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectStreamField;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Set;
 import java.util.Map;
-import java.util.HashMap;
 import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.loader.BootLoader;
 import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.loader.ResourceHelper;
+import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.misc.VM;
+import jdk.internal.module.ModuleHashes;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.ConstantPool;
 import jdk.internal.reflect.Reflection;
@@ -442,21 +451,10 @@
 
         PrivilegedAction<ClassLoader> pa = module::getClassLoader;
         ClassLoader cl = AccessController.doPrivileged(pa);
-        if (module.isNamed() && cl != null) {
-            return cl.loadLocalClass(module, name);
-        }
-
-        final Class<?> c;
         if (cl != null) {
-            c = cl.loadLocalClass(name);
+            return cl.loadClass(module, name);
         } else {
-            c = BootLoader.loadClassOrNull(name);
-        }
-
-        if (c != null && c.getModule() == module) {
-            return c;
-        } else {
-            return null;
+            return BootLoader.loadClass(module, name);
         }
     }
 
@@ -979,7 +977,7 @@
     }
 
     // cached package name
-    private String packageName;
+    private transient String packageName;
 
     /**
      * Returns the interfaces directly implemented by the class or interface
@@ -1976,6 +1974,22 @@
         return method;
     }
 
+    /**
+     * Returns a {@code Method} object that reflects the specified public
+     * member method of the class or interface represented by this
+     * {@code Class} object.
+     *
+     * @param name the name of the method
+     * @param parameterTypes the list of parameters
+     * @return the {@code Method} object that matches the specified
+     *         {@code name} and {@code parameterTypes}; {@code null}
+     *         if the method is not found or the name is
+     *         "&lt;init&gt;"or "&lt;clinit&gt;".
+     */
+    Method getMethodOrNull(String name, Class<?>... parameterTypes) {
+        return getMethod0(name, parameterTypes, true);
+    }
+
 
     /**
      * Returns a {@code Constructor} object that reflects the specified
@@ -2367,12 +2381,17 @@
     }
 
     /**
-     * Finds a resource with a given name. If this class is in a named {@link
-     * Module Module}, and the caller of this method is in the same module,
-     * then this method will attempt to find the resource in that module.
-     * Otherwise, the rules for searching resources
-     * associated with a given class are implemented by the defining
-     * {@linkplain ClassLoader class loader} of the class.  This method
+     * Finds a resource with a given name.
+     *
+     * <p> If this class is in a named {@link Module Module} then this method
+     * will attempt to find the resource in the module by means of the absolute
+     * resource name, subject to the rules for encapsulation specified in the
+     * {@code Module} {@link Module#getResourceAsStream getResourceAsStream}
+     * method.
+     *
+     * <p> Otherwise, if this class is not in a named module then the rules for
+     * searching resources associated with a given class are implemented by the
+     * defining {@linkplain ClassLoader class loader} of the class.  This method
      * delegates to this object's class loader.  If this object was loaded by
      * the bootstrap class loader, the method delegates to {@link
      * ClassLoader#getSystemResourceAsStream}.
@@ -2400,8 +2419,11 @@
      * </ul>
      *
      * @param  name name of the desired resource
-     * @return  A {@link java.io.InputStream} object or {@code null} if
-     *          no resource with this name is found
+     * @return  A {@link java.io.InputStream} object; {@code null} if no
+     *          resource with this name is found, the resource is in a package
+     *          that is not {@link Module#isOpen(String, Module) open} to at
+     *          least the caller module, or access to the resource is denied
+     *          by the security manager.
      * @throws  NullPointerException If {@code name} is {@code null}
      * @since  1.1
      */
@@ -2409,35 +2431,41 @@
     public InputStream getResourceAsStream(String name) {
         name = resolveName(name);
 
-        // if this Class and the caller are in the same named module
-        // then attempt to get an input stream to the resource in the
-        // module
         Module module = getModule();
         if (module.isNamed()) {
-            Class<?> caller = Reflection.getCallerClass();
-            if (caller != null && caller.getModule() == module) {
-                ClassLoader cl = getClassLoader0();
-                String mn = module.getName();
-                try {
-
-                    // special-case built-in class loaders to avoid the
-                    // need for a URL connection
-                    if (cl == null) {
-                        return BootLoader.findResourceAsStream(mn, name);
-                    } else if (cl instanceof BuiltinClassLoader) {
-                        return ((BuiltinClassLoader) cl).findResourceAsStream(mn, name);
-                    } else {
-                        URL url = cl.findResource(mn, name);
-                        return (url != null) ? url.openStream() : null;
+            if (!ResourceHelper.isSimpleResource(name)) {
+                Module caller = Reflection.getCallerClass().getModule();
+                if (caller != module) {
+                    Set<String> packages = module.getDescriptor().packages();
+                    String pn = ResourceHelper.getPackageName(name);
+                    if (packages.contains(pn) && !module.isOpen(pn, caller)) {
+                        // resource is in package not open to caller
+                        return null;
                     }
-
-                } catch (IOException | SecurityException e) {
-                    return null;
                 }
             }
+
+            String mn = module.getName();
+            ClassLoader cl = getClassLoader0();
+            try {
+
+                // special-case built-in class loaders to avoid the
+                // need for a URL connection
+                if (cl == null) {
+                    return BootLoader.findResourceAsStream(mn, name);
+                } else if (cl instanceof BuiltinClassLoader) {
+                    return ((BuiltinClassLoader) cl).findResourceAsStream(mn, name);
+                } else {
+                    URL url = cl.findResource(mn, name);
+                    return (url != null) ? url.openStream() : null;
+                }
+
+            } catch (IOException | SecurityException e) {
+                return null;
+            }
         }
 
-        // this Class and caller not in the same named module
+        // unnamed module
         ClassLoader cl = getClassLoader0();
         if (cl == null) {
             return ClassLoader.getSystemResourceAsStream(name);
@@ -2447,12 +2475,17 @@
     }
 
     /**
-     * Finds a resource with a given name. If this class is in a named {@link
-     * Module Module}, and the caller of this method is in the same module,
-     * then this method will attempt to find the resource in that module.
-     * Otherwise, the rules for searching resources
-     * associated with a given class are implemented by the defining
-     * {@linkplain ClassLoader class loader} of the class.  This method
+     * Finds a resource with a given name.
+     *
+     * <p> If this class is in a named {@link Module Module} then this method
+     * will attempt to find the resource in the module by means of the absolute
+     * resource name, subject to the rules for encapsulation specified in the
+     * {@code Module} {@link Module#getResourceAsStream getResourceAsStream}
+     * method.
+     *
+     * <p> Otherwise, if this class is not in a named module then the rules for
+     * searching resources associated with a given class are implemented by the
+     * defining {@linkplain ClassLoader class loader} of the class.  This method
      * delegates to this object's class loader. If this object was loaded by
      * the bootstrap class loader, the method delegates to {@link
      * ClassLoader#getSystemResource}.
@@ -2479,35 +2512,46 @@
      * </ul>
      *
      * @param  name name of the desired resource
-     * @return A {@link java.net.URL} object; {@code null} if no
-     *         resource with this name is found or the resource cannot
-     *         be located by a URL.
+     * @return A {@link java.net.URL} object; {@code null} if no resource with
+     *         this name is found, the resource cannot be located by a URL, the
+     *         resource is in a package that is not
+     *         {@link Module#isOpen(String, Module) open} to at least the caller
+     *         module, or access to the resource is denied by the security
+     *         manager.
+     * @throws NullPointerException If {@code name} is {@code null}
      * @since  1.1
      */
     @CallerSensitive
     public URL getResource(String name) {
         name = resolveName(name);
 
-        // if this Class and the caller are in the same named module
-        // then attempt to get URL to the resource in the module
         Module module = getModule();
         if (module.isNamed()) {
-            Class<?> caller = Reflection.getCallerClass();
-            if (caller != null && caller.getModule() == module) {
-                String mn = getModule().getName();
-                ClassLoader cl = getClassLoader0();
-                try {
-                    if (cl == null) {
-                        return BootLoader.findResource(mn, name);
-                    } else {
-                        return cl.findResource(mn, name);
+            if (!ResourceHelper.isSimpleResource(name)) {
+                Module caller = Reflection.getCallerClass().getModule();
+                if (caller != module) {
+                    Set<String> packages = module.getDescriptor().packages();
+                    String pn = ResourceHelper.getPackageName(name);
+                    if (packages.contains(pn) && !module.isOpen(pn, caller)) {
+                        // resource is in package not open to caller
+                        return null;
                     }
-                } catch (IOException ioe) {
-                    return null;
                 }
             }
+            String mn = getModule().getName();
+            ClassLoader cl = getClassLoader0();
+            try {
+                if (cl == null) {
+                    return BootLoader.findResource(mn, name);
+                } else {
+                    return cl.findResource(mn, name);
+                }
+            } catch (IOException ioe) {
+                return null;
+            }
         }
 
+        // unnamed module
         ClassLoader cl = getClassLoader0();
         if (cl == null) {
             return ClassLoader.getSystemResource(name);
@@ -2632,9 +2676,6 @@
      * if name is absolute
      */
     private String resolveName(String name) {
-        if (name == null) {
-            return name;
-        }
         if (!name.startsWith("/")) {
             Class<?> c = this;
             while (c.isArray()) {
diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
index adffac1..3778fc8 100644
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
@@ -42,15 +42,14 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Set;
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.Stack;
-import java.util.NoSuchElementException;
 import java.util.Vector;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
@@ -59,7 +58,6 @@
 import java.util.stream.StreamSupport;
 
 import jdk.internal.perf.PerfCounter;
-import jdk.internal.module.ServicesCatalog;
 import jdk.internal.loader.BootLoader;
 import jdk.internal.loader.ClassLoaders;
 import jdk.internal.misc.SharedSecrets;
@@ -411,7 +409,6 @@
         this(checkCreateClassLoader(), null, parent);
     }
 
-
     /**
      * Creates a new class loader using the <tt>ClassLoader</tt> returned by
      * the method {@link #getSystemClassLoader()
@@ -431,7 +428,6 @@
         this(checkCreateClassLoader(), null, getSystemClassLoader());
     }
 
-
     /**
      * Returns the name of this class loader or {@code null} if
      * this class loader is not named.
@@ -581,7 +577,7 @@
      * @return The resulting {@code Class} object in a module defined by
      *         this class loader, or {@code null} if the class could not be found.
      */
-    final Class<?> loadLocalClass(Module module, String name) {
+    final Class<?> loadClass(Module module, String name) {
         synchronized (getClassLoadingLock(name)) {
             // First, check if the class has already been loaded
             Class<?> c = findLoadedClass(name);
@@ -597,34 +593,6 @@
     }
 
     /**
-     * Loads the class with the specified <a href="#name">binary name</a>
-     * defined by this class loader.  This method returns {@code null}
-     * if the class could not be found.
-     *
-     * @apiNote This method does not delegate to the parent class loader.
-     *
-     * @param  name
-     *         The <a href="#name">binary name</a> of the class
-     *
-     * @return The resulting {@code Class} object in a module defined by
-     *         this class loader, or {@code null} if the class could not be found.
-     */
-    final Class<?> loadLocalClass(String name) {
-        synchronized (getClassLoadingLock(name)) {
-            // First, check if the class has already been loaded
-            Class<?> c = findLoadedClass(name);
-            if (c == null) {
-                try {
-                    return findClass(name);
-                } catch (ClassNotFoundException e) {
-                    // ignore
-                }
-            }
-            return c;
-        }
-    }
-
-    /**
      * Returns the lock object for class loading operations.
      * For backward compatibility, the default implementation of this method
      * behaves as follows. If this ClassLoader object is registered as
@@ -724,12 +692,17 @@
      * should override this method.
      *
      * @apiNote This method returns {@code null} rather than throwing
-     *          {@code ClassNotFoundException} if the class could not be found
+     *          {@code ClassNotFoundException} if the class could not be found.
      *
-     * @implSpec The default implementation returns {@code null}.
+     * @implSpec The default implementation attempts to find the class by
+     * invoking {@link #findClass(String)} when the {@code moduleName} is
+     * {@code null}. It otherwise returns {@code null}.
      *
      * @param  moduleName
-     *         The module name
+     *         The module name; or {@code null} to find the class in the
+     *         {@linkplain #getUnnamedModule() unnamed module} for this
+     *         class loader
+
      * @param  name
      *         The <a href="#name">binary name</a> of the class
      *
@@ -739,6 +712,11 @@
      * @since 9
      */
     protected Class<?> findClass(String moduleName, String name) {
+        if (moduleName == null) {
+            try {
+                return findClass(name);
+            } catch (ClassNotFoundException ignore) { }
+        }
         return null;
     }
 
@@ -1286,10 +1264,20 @@
      * Class loader implementations that support the loading from modules
      * should override this method.
      *
-     * @implSpec The default implementation returns {@code null}.
+     * @apiNote This method is the basis for the {@code Class} {@link
+     * Class#getResource getResource} and {@link Class#getResourceAsStream
+     * getResourceAsStream} methods. It is not subject to the rules for
+     * encapsulation specified by {@code Module} {@link
+     * Module#getResourceAsStream getResourceAsStream}.
+     *
+     * @implSpec The default implementation attempts to find the resource by
+     * invoking {@link #findResource(String)} when the {@code moduleName} is
+     * {@code null}. It otherwise returns {@code null}.
      *
      * @param  moduleName
-     *         The module name
+     *         The module name; or {@code null} to find a resource in the
+     *         {@linkplain #getUnnamedModule() unnamed module} for this
+     *         class loader
      * @param  name
      *         The resource name
      *
@@ -1306,7 +1294,11 @@
      * @since 9
      */
     protected URL findResource(String moduleName, String name) throws IOException {
-        return null;
+        if (moduleName == null) {
+            return findResource(name);
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -1314,9 +1306,6 @@
      * (images, audio, text, etc) that can be accessed by class code in a way
      * that is independent of the location of the code.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resource in named modules.
-     *
      * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
      * identifies the resource.
      *
@@ -1325,16 +1314,31 @@
      * built-in to the virtual machine is searched.  That failing, this method
      * will invoke {@link #findResource(String)} to find the resource.  </p>
      *
-     * @apiNote When overriding this method it is recommended that an
-     * implementation ensures that any delegation is consistent with the {@link
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally (even if the caller of this method is in the
+     * same module as the resource). </p>
+     *
+     * @apiNote Where several modules are defined to the same class loader,
+     * and where more than one module contains a resource with the given name,
+     * then the ordering that modules are searched is not specified and may be
+     * very unpredictable.
+     * When overriding this method it is recommended that an implementation
+     * ensures that any delegation is consistent with the {@link
      * #getResources(java.lang.String) getResources(String)} method.
      *
      * @param  name
      *         The resource name
      *
-     * @return  A <tt>URL</tt> object for reading the resource, or
-     *          <tt>null</tt> if the resource could not be found or the invoker
-     *          doesn't have adequate  privileges to get the resource.
+     * @return  {@code URL} object for reading the resource; {@code null} if
+     *          the resource could not be found, a {@code 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
+     *          denied by the security manager.
+     *
      * @throws  NullPointerException If {@code name} is {@code null}
      *
      * @since  1.1
@@ -1358,16 +1362,24 @@
      * (images, audio, text, etc) that can be accessed by class code in a way
      * that is independent of the location of the code.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules.
-     *
-     * <p>The name of a resource is a <tt>/</tt>-separated path name that
+     * <p> The name of a resource is a <tt>/</tt>-separated path name that
      * identifies the resource.
      *
-     * <p> The search order is described in the documentation for {@link
-     * #getResource(String)}.  </p>
+     * <p> The delegation order for searching is described in the documentation
+     * for {@link #getResource(String)}.  </p>
      *
-     * @apiNote When overriding this method it is recommended that an
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally (even if the caller of this method is in the
+     * same module as the resource).</p>
+     *
+     * @apiNote Where several modules are defined to the same class loader,
+     * and where more than one module contains a resource with the given name,
+     * then the ordering is not specified and may be very unpredictable.
+     * When overriding this method it is recommended that an
      * implementation ensures that any delegation is consistent with the {@link
      * #getResource(java.lang.String) getResource(String)} method. This should
      * ensure that the first element returned by the Enumeration's
@@ -1378,9 +1390,11 @@
      *         The resource name
      *
      * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
-     *          the resource.  If no resources could  be found, the enumeration
-     *          will be empty.  Resources that the class loader doesn't have
-     *          access to will not be in the enumeration.
+     *          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,
+     *          or access to the resource is denied by the security manager,
+     *          are not returned in the enumeration.
      *
      * @throws  IOException
      *          If I/O errors occur
@@ -1410,9 +1424,6 @@
      * can be accessed by class code in a way that is independent of the
      * location of the code.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules.
-     *
      * <p> The name of a resource is a {@code /}-separated path name that
      * identifies the resource.
      *
@@ -1424,6 +1435,14 @@
      * exception is wrapped in an {@link UncheckedIOException} that is then
      * thrown.
      *
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally (even if the caller of this method is in the
+     * same module as the resource). </p>
+     *
      * @apiNote When overriding this method it is recommended that an
      * implementation ensures that any delegation is consistent with the {@link
      * #getResource(java.lang.String) getResource(String)} method. This should
@@ -1434,9 +1453,10 @@
      *         The resource name
      *
      * @return  A stream of resource {@link java.net.URL URL} objects. If no
-     *          resources could  be found, the stream will be empty.  Resources
-     *          that the class loader doesn't have access to will not be in the
-     *          stream.
+     *          resources could  be found, the stream will be empty. Resources
+     *          for which a {@code URL} cannot be constructed, are in a package
+     *          that is not opened unconditionally, or access to the resource
+     *          is denied by the security manager, will not be in the stream.
      *
      * @throws  NullPointerException If {@code name} is {@code null}
      *
@@ -1462,14 +1482,21 @@
      * Finds the resource with the given name. Class loader implementations
      * should override this method to specify where to find resources.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules defined to this class loader.
+     * <p> For resources in named modules then the method must implement the
+     * rules for encapsulation specified in the {@code Module} {@link
+     * Module#getResourceAsStream getResourceAsStream} method. Additionally,
+     * it must not find non-"{@code .class}" resources in packages of named
+     * modules unless the package is {@link Module#isOpen(String) opened}
+     * unconditionally. </p>
      *
      * @param  name
      *         The resource name
      *
-     * @return  A <tt>URL</tt> object for reading the resource, or
-     *          <tt>null</tt> if the resource could not be found
+     * @return  {@code URL} object for reading the resource; {@code null} if
+     *          the resource could not be found, a {@code 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
+     *          denied by the security manager.
      *
      * @since  1.2
      */
@@ -1483,14 +1510,22 @@
      * implementations should override this method to specify where to load
      * resources from.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules defined to this class loader.
+     * <p> For resources in named modules then the method must implement the
+     * rules for encapsulation specified in the {@code Module} {@link
+     * Module#getResourceAsStream getResourceAsStream} method. Additionally,
+     * it must not find non-"{@code .class}" resources in packages of named
+     * modules unless the package is {@link Module#isOpen(String) opened}
+     * unconditionally. </p>
      *
      * @param  name
      *         The resource name
      *
      * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
-     *          the resources
+     *          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,
+     *          or access to the resource is denied by the security manager,
+     *          are not returned in the enumeration.
      *
      * @throws  IOException
      *          If I/O errors occur
@@ -1498,7 +1533,7 @@
      * @since  1.2
      */
     protected Enumeration<URL> findResources(String name) throws IOException {
-        return java.util.Collections.emptyEnumeration();
+        return Collections.emptyEnumeration();
     }
 
     /**
@@ -1549,14 +1584,21 @@
      * classes.  This method locates the resource through the system class
      * loader (see {@link #getSystemClassLoader()}).
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules.
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally. </p>
      *
      * @param  name
      *         The resource name
      *
-     * @return  A {@link java.net.URL <tt>URL</tt>} object for reading the
-     *          resource, or <tt>null</tt> if the resource could not be found
+     * @return  A {@link java.net.URL <tt>URL</tt>} 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
+     *          denied by the security manager.
      *
      * @since  1.1
      */
@@ -1570,17 +1612,25 @@
      * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
      * java.net.URL <tt>URL</tt>} objects.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules.
-     *
      * <p> The search order is described in the documentation for {@link
      * #getSystemResource(String)}.  </p>
      *
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally. </p>
+     *
      * @param  name
      *         The resource name
      *
-     * @return  An enumeration of resource {@link java.net.URL <tt>URL</tt>}
-     *          objects
+     * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} 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,
+     *          or access to the resource is denied by the security manager,
+     *          are not returned in the enumeration.
      *
      * @throws  IOException
      *          If I/O errors occur
@@ -1596,17 +1646,24 @@
     /**
      * Returns an input stream for reading the specified resource.
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules.
-     *
      * <p> The search order is described in the documentation for {@link
      * #getResource(String)}.  </p>
      *
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally. </p>
+     *
      * @param  name
      *         The resource name
      *
-     * @return  An input stream for reading the resource, or <tt>null</tt>
-     *          if the resource could not be found
+     * @return  An input stream for reading the resource; {@code null} if the
+     *          resource could not be found, the resource is in a package that
+     *          is not opened unconditionally, or access to the resource is
+     *          denied by the security manager.
+     *
      * @throws  NullPointerException If {@code name} is {@code null}
      *
      * @since  1.1
@@ -1626,14 +1683,20 @@
      * used to load classes.  This method locates the resource through the
      * system class loader (see {@link #getSystemClassLoader()}).
      *
-     * Resources in a named module are private to that module. This method does
-     * not find resources in named modules.
+     * <p> Resources in named modules are subject to the encapsulation rules
+     * specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     * Additionally, and except for the special case where the resource has a
+     * name ending with "{@code .class}", this method will only find resources in
+     * packages of named modules when the package is {@link Module#isOpen(String)
+     * opened} unconditionally. </p>
      *
      * @param  name
      *         The resource name
      *
-     * @return  An input stream for reading the resource, or <tt>null</tt>
-     *          if the resource could not be found
+     * @return  An input stream for reading the resource; {@code null} if the
+     *          resource could not be found, the resource is in a package that
+     *          is not opened unconditionally, or access to the resource is
+     *          denied by the security manager.
      *
      * @since  1.1
      */
@@ -2719,33 +2782,7 @@
     private static native AssertionStatusDirectives retrieveDirectives();
 
 
-    /**
-     * Returns the ServiceCatalog for modules defined to this class loader
-     * or {@code null} if this class loader does not have a services catalog.
-     */
-    ServicesCatalog getServicesCatalog() {
-        return servicesCatalog;
-    }
-
-    /**
-     * Returns the ServiceCatalog for modules defined to this class loader,
-     * creating it if it doesn't already exist.
-     */
-    ServicesCatalog createOrGetServicesCatalog() {
-        ServicesCatalog catalog = servicesCatalog;
-        if (catalog == null) {
-            catalog = ServicesCatalog.create();
-            boolean set = trySetObjectField("servicesCatalog", catalog);
-            if (!set) {
-                // beaten by someone else
-                catalog = servicesCatalog;
-            }
-        }
-        return catalog;
-    }
-
-    // the ServiceCatalog for modules associated with this class loader.
-    private volatile ServicesCatalog servicesCatalog;
+    // -- Misc --
 
     /**
      * Returns the ConcurrentHashMap used as a storage for ClassLoaderValue(s)
diff --git a/jdk/src/java.base/share/classes/java/lang/Deprecated.java b/jdk/src/java.base/share/classes/java/lang/Deprecated.java
index 2177694..673401c 100644
--- a/jdk/src/java.base/share/classes/java/lang/Deprecated.java
+++ b/jdk/src/java.base/share/classes/java/lang/Deprecated.java
@@ -40,6 +40,11 @@
  * annotation on a local variable declaration or on a parameter declaration
  * or a package declaration has no effect on the warnings issued by a compiler.
  *
+ * <p>When a module is deprecated, the use of that module in {@code
+ * requires}, but not in {@code exports} or {@code opens} clauses causes
+ * a warning to be issued. A module being deprecated does <em>not</em> cause
+ * warnings to be issued for uses of types within the module.
+ *
  * <p>This annotation type has a string-valued element {@code since}. The value
  * of this element indicates the version in which the annotated program element
  * was first deprecated.
@@ -74,7 +79,7 @@
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
-@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
+@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
 public @interface Deprecated {
     /**
      * Returns the version in which the annotated element became deprecated.
diff --git a/jdk/src/java.base/share/classes/java/lang/Iterable.java b/jdk/src/java.base/share/classes/java/lang/Iterable.java
index de91500..8905902 100644
--- a/jdk/src/java.base/share/classes/java/lang/Iterable.java
+++ b/jdk/src/java.base/share/classes/java/lang/Iterable.java
@@ -53,10 +53,13 @@
     /**
      * Performs the given action for each element of the {@code Iterable}
      * until all elements have been processed or the action throws an
-     * exception.  Unless otherwise specified by the implementing class,
-     * actions are performed in the order of iteration (if an iteration order
-     * is specified).  Exceptions thrown by the action are relayed to the
+     * exception.  Actions are performed in the order of iteration, if that
+     * order is specified.  Exceptions thrown by the action are relayed to the
      * caller.
+     * <p>
+     * The behavior of this method is unspecified if the action performs
+     * side-effects that modify the underlying source of elements, unless an
+     * overriding class has specified a concurrent modification policy.
      *
      * @implSpec
      * <p>The default implementation behaves as if:
diff --git a/jdk/src/java.base/share/classes/java/lang/Package.java b/jdk/src/java.base/share/classes/java/lang/Package.java
index b4ba45b..5a19f97 100644
--- a/jdk/src/java.base/share/classes/java/lang/Package.java
+++ b/jdk/src/java.base/share/classes/java/lang/Package.java
@@ -398,10 +398,16 @@
         if (packageInfo == null) {
             // find package-info.class defined by loader
             String cn = packageName() + ".package-info";
-            PrivilegedAction<ClassLoader> pa = module()::getClassLoader;
+            Module module = module();
+            PrivilegedAction<ClassLoader> pa = module::getClassLoader;
             ClassLoader loader = AccessController.doPrivileged(pa);
-            Class<?> c = loader != null ? loader.loadLocalClass(cn)
-                                        : BootLoader.loadClassOrNull(cn);
+            Class<?> c;
+            if (loader != null) {
+                c = loader.loadClass(module, cn);
+            } else {
+                c = BootLoader.loadClass(module, cn);
+            }
+
             if (c != null) {
                 packageInfo = c;
             } else {
diff --git a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java
index 600bdd4..2c0dd91 100644
--- a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java
+++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java
@@ -811,7 +811,9 @@
                 throw new NullPointerException();
             if (((a = array).length >> 1) >= (hi = fence) &&
                 (i = index) >= 0 && i < (index = hi)) {
-                do { action.accept(getChar(a, i)); } while (++i < hi);
+                do {
+                    action.accept(charAt(a, i));
+                } while (++i < hi);
             }
         }
 
@@ -819,8 +821,10 @@
         public boolean tryAdvance(IntConsumer action) {
             if (action == null)
                 throw new NullPointerException();
-            if (index >= 0 && index < fence) {
-                action.accept(getChar(array, index++));
+            int i = index;
+            if (i >= 0 && i < fence) {
+                action.accept(charAt(array, i));
+                index++;
                 return true;
             }
             return false;
@@ -860,8 +864,8 @@
 
             int midOneLess;
             // If the mid-point intersects a surrogate pair
-            if (Character.isLowSurrogate(getChar(array, mid)) &&
-                Character.isHighSurrogate(getChar(array, midOneLess = (mid -1)))) {
+            if (Character.isLowSurrogate(charAt(array, mid)) &&
+                Character.isHighSurrogate(charAt(array, midOneLess = (mid -1)))) {
                 // If there is only one pair it cannot be split
                 if (lo >= midOneLess)
                     return null;
@@ -898,10 +902,10 @@
         // Advance one code point from the index, i, and return the next
         // index to advance from
         private static int advance(byte[] a, int i, int hi, IntConsumer action) {
-            char c1 = getChar(a, i++);
+            char c1 = charAt(a, i++);
             int cp = c1;
             if (Character.isHighSurrogate(c1) && i < hi) {
-                char c2 = getChar(a, i);
+                char c2 = charAt(a, i);
                 if (Character.isLowSurrogate(c2)) {
                     i++;
                     cp = Character.toCodePoint(c1, c2);
diff --git a/jdk/src/java.base/share/classes/java/lang/SuppressWarnings.java b/jdk/src/java.base/share/classes/java/lang/SuppressWarnings.java
index 8401779..1f4e0e0 100644
--- a/jdk/src/java.base/share/classes/java/lang/SuppressWarnings.java
+++ b/jdk/src/java.base/share/classes/java/lang/SuppressWarnings.java
@@ -35,6 +35,9 @@
  * a superset of the warnings suppressed in all containing elements.  For
  * example, if you annotate a class to suppress one warning and annotate a
  * method to suppress another, both warnings will be suppressed in the method.
+ * However, note that if a warning is suppressed in a {@code
+ * module-info} file, the suppression applies to elements within the
+ * file and <em>not</em> to types contained within the module.
  *
  * <p>As a matter of style, programmers should always use this annotation
  * on the most deeply nested element where it is effective.  If you want to
@@ -49,7 +52,7 @@
  * @jls 5.5.2 Checked Casts and Unchecked Casts
  * @jls 9.6.4.5 @SuppressWarnings
  */
-@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
+@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
 @Retention(RetentionPolicy.SOURCE)
 public @interface SuppressWarnings {
     /**
diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java
index 4bce8bb..1862077 100644
--- a/jdk/src/java.base/share/classes/java/lang/System.java
+++ b/jdk/src/java.base/share/classes/java/lang/System.java
@@ -38,6 +38,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Layer;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Module;
 import java.net.URL;
@@ -69,7 +70,6 @@
 import jdk.internal.logger.LocalizedLoggerWrapper;
 
 import jdk.internal.module.ModuleBootstrap;
-import jdk.internal.module.ServicesCatalog;
 
 /**
  * The <code>System</code> class contains several useful class fields
@@ -1987,7 +1987,10 @@
 
     private static void setJavaLangAccess() {
         // Allow privileged classes outside of java.lang
-        SharedSecrets.setJavaLangAccess(new JavaLangAccess(){
+        SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
+            public Method getMethodOrNull(Class<?> klass, String name, Class<?>... parameterTypes) {
+                return klass.getMethodOrNull(name, parameterTypes);
+            }
             public jdk.internal.reflect.ConstantPool getConstantPool(Class<?> klass) {
                 return klass.getConstantPool();
             }
@@ -2031,12 +2034,6 @@
             public Layer getBootLayer() {
                 return bootLayer;
             }
-            public ServicesCatalog getServicesCatalog(ClassLoader cl) {
-                return cl.getServicesCatalog();
-            }
-            public ServicesCatalog createOrGetServicesCatalog(ClassLoader cl) {
-                return cl.createOrGetServicesCatalog();
-            }
             public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
                 return cl.createOrGetClassLoaderValueMap();
             }
diff --git a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
index d3c86a2..367103a 100644
--- a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
+++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template
@@ -123,27 +123,25 @@
 
     /**
      * In case you were wondering this method is called by java -version.
-     * Sad that it prints to stderr; would be nicer if default printed on
-     * stdout.
      */
-    public static void print() {
-        print(System.err);
+    public static void print(boolean err) {
+        print(err, false);
     }
 
     /**
      * This is the same as print except that it adds an extra line-feed
      * at the end, typically used by the -showversion in the launcher
      */
-    public static void println() {
-        print(System.err);
-        System.err.println();
+    public static void println(boolean err) {
+        print(err, true);
     }
 
     /**
-     * Give a stream, it will print version info on it.
+     * Print version info.
      */
-    public static void print(PrintStream ps) {
+    private static void print(boolean err, boolean newln) {
         boolean isHeadless = false;
+        PrintStream ps = err ? System.err : System.out;
 
         /* Report that we're running headless if the property is true */
         String headless = System.getProperty("java.awt.headless");
@@ -152,10 +150,14 @@
         }
 
         /* First line: platform version. */
-        ps.println(launcher_name + " version \"" + java_version + "\"");
+        if (err) {
+            ps.println(launcher_name + " version \"" + java_version + "\"");
+        } else {
+            /* Use a format more in line with GNU conventions */
+            ps.println(launcher_name + " " + java_version);
+        }
 
         /* Second line: runtime version (ie, libraries). */
-
         String jdk_debug_level = System.getProperty("jdk.debug", "release");
         /* Debug level is not printed for "release" builds */
         if ("release".equals(jdk_debug_level)) {
diff --git a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java
index c32ae6a..14780fe 100644
--- a/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java
+++ b/jdk/src/java.base/share/classes/java/lang/annotation/ElementType.java
@@ -37,10 +37,10 @@
  * <em>type contexts</em> , where annotations apply to types used in
  * declarations and expressions.
  *
- * <p>The constants {@link #ANNOTATION_TYPE} , {@link #CONSTRUCTOR} , {@link
- * #FIELD} , {@link #LOCAL_VARIABLE} , {@link #METHOD} , {@link #PACKAGE} ,
- * {@link #PARAMETER} , {@link #TYPE} , and {@link #TYPE_PARAMETER} correspond
- * to the declaration contexts in JLS 9.6.4.1.
+ * <p>The constants {@link #ANNOTATION_TYPE}, {@link #CONSTRUCTOR}, {@link
+ * #FIELD}, {@link #LOCAL_VARIABLE}, {@link #METHOD}, {@link #PACKAGE}, {@link
+ * #MODULE}, {@link #PARAMETER}, {@link #TYPE}, and {@link #TYPE_PARAMETER}
+ * correspond to the declaration contexts in JLS 9.6.4.1.
  *
  * <p>For example, an annotation whose type is meta-annotated with
  * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a
@@ -107,5 +107,12 @@
      *
      * @since 1.8
      */
-    TYPE_USE
+    TYPE_USE,
+
+    /**
+     * Module declaration.
+     *
+     * @since 9
+     */
+    MODULE
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index 05ef3c9..010b6180 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -1147,12 +1147,14 @@
 
         static
         MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
-            // Do not use this function to inject calls into system classes.
+            // Code in the the boot layer should now be careful while creating method handles or
+            // functional interface instances created from method references to @CallerSensitive  methods,
+            // it needs to be ensured the handles or interface instances are kept safe and are not passed
+            // from the boot layer to untrusted code.
             if (hostClass == null
                 ||    (hostClass.isArray() ||
                        hostClass.isPrimitive() ||
-                       hostClass.getName().startsWith("java.") ||
-                       hostClass.getName().startsWith("sun."))) {
+                       hostClass.getName().startsWith("java.lang.invoke."))) {
                 throw new InternalError();  // does not happen, and should not anyway
             }
             // For simplicity, convert mh to a varargs-like method.
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index e1fad4d..0c9da2c 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -42,6 +42,7 @@
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
 import java.lang.reflect.ReflectPermission;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
@@ -142,6 +143,59 @@
     }
 
     /**
+     * Returns a {@link Lookup lookup object} with full capabilities to emulate all
+     * supported bytecode behaviors, including <a href="MethodHandles.Lookup.html#privacc">
+     * private access</a>, on a target class.
+     * This method checks that a caller, specified as a {@code Lookup} object, is allowed to
+     * do <em>deep reflection</em> on the target class. If {@code m1} is the module containing
+     * the {@link Lookup#lookupClass() lookup class}, and {@code m2} is the module containing
+     * the target class, then this check ensures that
+     * <ul>
+     *     <li>{@code m1} {@link Module#canRead reads} {@code m2}.</li>
+     *     <li>{@code m2} {@link Module#isOpen(String,Module) opens} the package containing
+     *     the target class to at least {@code m1}.</li>
+     *     <li>The lookup has the {@link Lookup#MODULE MODULE} lookup mode.</li>
+     * </ul>
+     * <p>
+     * If there is a security manager, its {@code checkPermission} method is called to
+     * check {@code ReflectPermission("suppressAccessChecks")}.
+     * @apiNote The {@code MODULE} lookup mode serves to authenticate that the lookup object
+     * was created by code in the caller module (or derived from a lookup object originally
+     * created by the caller). A lookup object with the {@code MODULE} lookup mode can be
+     * shared with trusted parties without giving away {@code PRIVATE} and {@code PACKAGE}
+     * access to the caller.
+     * @param targetClass the target class
+     * @param lookup the caller lookup object
+     * @return a lookup object for the target class, with private access
+     * @throws IllegalArgumentException if {@code targetClass} is a primitve type or array class
+     * @throws NullPointerException if {@code targetClass} or {@code caller} is {@code null}
+     * @throws IllegalAccessException if the access check specified above fails
+     * @throws SecurityException if denied by the security manager
+     * @since 9
+     */
+    public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
+        if (targetClass.isPrimitive())
+            throw new IllegalArgumentException(targetClass + " is a primitive class");
+        if (targetClass.isArray())
+            throw new IllegalArgumentException(targetClass + " is an array class");
+        Module targetModule = targetClass.getModule();
+        Module callerModule = lookup.lookupClass().getModule();
+        if (callerModule != targetModule && targetModule.isNamed()) {
+            if (!callerModule.canRead(targetModule))
+                throw new IllegalAccessException(callerModule + " does not read " + targetModule);
+            String pn = targetClass.getPackageName();
+            assert pn != null && pn.length() > 0 : "unnamed package cannot be in named module";
+            if (!targetModule.isOpen(pn, callerModule))
+                throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule);
+        }
+        if ((lookup.lookupModes() & Lookup.MODULE) == 0)
+            throw new IllegalAccessException("lookup does not have MODULE lookup mode");
+        return new Lookup(targetClass);
+    }
+
+    /**
      * Performs an unchecked "crack" of a
      * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
      * The result is as if the user had obtained a lookup object capable enough
@@ -1807,7 +1861,12 @@
             return callerClass;
         }
 
-        private boolean hasPrivateAccess() {
+        /**
+         * Returns {@code true} if this lookup has {@code PRIVATE} access.
+         * @return {@code true} if this lookup has {@code PRIVATE} acesss.
+         * @since 9
+         */
+        public boolean hasPrivateAccess() {
             return (allowedModes & PRIVATE) != 0;
         }
 
diff --git a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
index d1efde87..9753569 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java
@@ -26,14 +26,20 @@
 package java.lang.module;
 
 import java.io.PrintStream;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * The configuration that is the result of resolution or resolution with
@@ -46,14 +52,14 @@
  * dependences expressed by {@code requires} clauses.
  *
  * The <em>dependence graph</em> is augmented with edges that take account of
- * implicitly declared dependences ({@code requires public}) to create a
+ * implicitly declared dependences ({@code requires transitive}) to create a
  * <em>readability graph</em>. A {@code Configuration} encapsulates the
  * resulting graph of {@link ResolvedModule resolved modules}.
  *
  * <p> Suppose we have the following observable modules: </p>
  * <pre> {@code
  *     module m1 { requires m2; }
- *     module m2 { requires public m3; }
+ *     module m2 { requires transitive m3; }
  *     module m3 { }
  *     module m4 { }
  * } </pre>
@@ -70,8 +76,10 @@
  * <p> Resolution is an additive process. When computing the transitive closure
  * then the dependence relation may include dependences on modules in parent
  * configurations. The result is a <em>relative configuration</em> that is
- * relative to a parent configuration and where the readability graph may have
- * edges from modules in the configuration to modules in a parent configuration.
+ * relative to one or more parent configurations and where the readability graph
+ * may have edges from modules in the configuration to modules in parent
+ * configurations.
+ *
  * </p>
  *
  * <p> Suppose we have the following observable modules: </p>
@@ -96,9 +104,9 @@
  * <p> {@link ModuleDescriptor#isAutomatic() Automatic} modules receive special
  * treatment during resolution. Each automatic module is resolved so that it
  * reads all other modules in the configuration and all parent configurations.
- * Each automatic module is also resolved as if it {@code requires public} all
- * other automatic modules in the configuration (and all automatic modules in
- * parent configurations). </p>
+ * Each automatic module is also resolved as if it {@code requires transitive}
+ * all other automatic modules in the configuration (and all automatic modules
+ * in parent configurations). </p>
 
  * <h2><a name="servicebinding">Service binding</a></h2>
  *
@@ -171,54 +179,157 @@
     // @see Configuration#empty()
     private static final Configuration EMPTY_CONFIGURATION = new Configuration();
 
-    private final Configuration parent;
+    // parent configurations, in search order
+    private final List<Configuration> parents;
 
     private final Map<ResolvedModule, Set<ResolvedModule>> graph;
     private final Set<ResolvedModule> modules;
     private final Map<String, ResolvedModule> nameToModule;
 
     private Configuration() {
-        this.parent = null;
+        this.parents = Collections.emptyList();
         this.graph = Collections.emptyMap();
         this.modules = Collections.emptySet();
         this.nameToModule = Collections.emptyMap();
     }
 
-    private Configuration(Configuration parent,
+    private Configuration(List<Configuration> parents,
                           Resolver resolver,
                           boolean check)
     {
         Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check);
 
-        Map<String, ResolvedModule> nameToModule = new HashMap<>();
+        @SuppressWarnings(value = {"rawtypes", "unchecked"})
+        Entry<String, ResolvedModule>[] nameEntries
+            = (Entry<String, ResolvedModule>[])new Entry[g.size()];
+        ResolvedModule[] moduleArray = new ResolvedModule[g.size()];
+        int i = 0;
         for (ResolvedModule resolvedModule : g.keySet()) {
-            nameToModule.put(resolvedModule.name(), resolvedModule);
+            moduleArray[i] = resolvedModule;
+            nameEntries[i] = Map.entry(resolvedModule.name(), resolvedModule);
+            i++;
         }
 
-        this.parent = parent;
+        this.parents = Collections.unmodifiableList(parents);
         this.graph = g;
-        this.modules = Collections.unmodifiableSet(g.keySet());
-        this.nameToModule = Collections.unmodifiableMap(nameToModule);
+        this.modules = Set.of(moduleArray);
+        this.nameToModule = Map.ofEntries(nameEntries);
     }
 
 
     /**
      * Resolves a collection of root modules, with this configuration as its
-     * parent, to create a new configuration.
+     * parent, to create a new configuration. This method works exactly as
+     * specified by the static {@link
+     * #resolveRequires(ModuleFinder,List,ModuleFinder,Collection) resolveRequires}
+     * method when invoked with this configuration as the parent. In other words,
+     * if this configuration is {@code cf} then this method is equivalent to
+     * invoking:
+     * <pre> {@code
+     *     Configuration.resolveRequires(before, List.of(cf), after, roots);
+     * }</pre>
+     *
+     * @param  before
+     *         The <em>before</em> module finder to find modules
+     * @param  after
+     *         The <em>after</em> module finder to locate modules when a
+     *         module cannot be located by the {@code before} module finder
+     *         and the module is not in this configuration
+     * @param  roots
+     *         The possibly-empty collection of module names of the modules
+     *         to resolve
+     *
+     * @return The configuration that is the result of resolving the given
+     *         root modules
+     *
+     * @throws ResolutionException
+     *         If resolution or the post-resolution checks fail
+     * @throws SecurityException
+     *         If locating a module is denied by the security manager
+     */
+    public Configuration resolveRequires(ModuleFinder before,
+                                         ModuleFinder after,
+                                         Collection<String> roots)
+    {
+        return resolveRequires(before, List.of(this), after, roots);
+    }
+
+
+    /**
+     * Resolves a collection of root modules, with service binding, and with
+     * this configuration as its parent, to create a new configuration.
+     * This method works exactly as specified by the static {@link
+     * #resolveRequiresAndUses(ModuleFinder,List,ModuleFinder,Collection)
+     * resolveRequiresAndUses} method when invoked with this configuration
+     * as the parent. In other words, if this configuration is {@code cf} then
+     * this method is equivalent to invoking:
+     * <pre> {@code
+     *     Configuration.resolveRequiresAndUses(before, List.of(cf), after, roots);
+     * }</pre>
+     *
+     *
+     * @param  before
+     *         The <em>before</em> module finder to find modules
+     * @param  after
+     *         The <em>after</em> module finder to locate modules when not
+     *         located by the {@code before} module finder and this
+     *         configuration
+     * @param  roots
+     *         The possibly-empty collection of module names of the modules
+     *         to resolve
+     *
+     * @return The configuration that is the result of resolving the given
+     *         root modules
+     *
+     * @throws ResolutionException
+     *         If resolution or the post-resolution checks fail
+     * @throws SecurityException
+     *         If locating a module is denied by the security manager
+     */
+    public Configuration resolveRequiresAndUses(ModuleFinder before,
+                                                ModuleFinder after,
+                                                Collection<String> roots)
+    {
+        return resolveRequiresAndUses(before, List.of(this), after, roots);
+    }
+
+
+    /**
+     * Resolves a collection of root modules, with service binding, and with
+     * the empty configuration as its parent. The post resolution checks
+     * are optionally run.
+     *
+     * This method is used to create the configuration for the boot layer.
+     */
+    static Configuration resolveRequiresAndUses(ModuleFinder finder,
+                                                Collection<String> roots,
+                                                boolean check,
+                                                PrintStream traceOutput)
+    {
+        List<Configuration> parents = List.of(empty());
+        Resolver resolver = new Resolver(finder, parents, ModuleFinder.of(), traceOutput);
+        resolver.resolveRequires(roots).resolveUses();
+
+        return new Configuration(parents, resolver, check);
+    }
+
+
+    /**
+     * Resolves a collection of root modules to create a configuration.
      *
      * <p> Each root module is located using the given {@code before} module
      * finder. If a module is not found then it is located in the parent
      * configuration as if by invoking the {@link #findModule(String)
-     * findModule} method. If not found then the module is located using the
-     * given {@code after} module finder. The same search order is used to
-     * locate transitive dependences. Root modules or dependences that are
-     * located in a parent configuration are resolved no further and are not
-     * included in the resulting configuration. </p>
+     * findModule} method on each parent in iteration order. If not found then
+     * the module is located using the given {@code after} module finder. The
+     * same search order is used to locate transitive dependences. Root modules
+     * or dependences that are located in a parent configuration are resolved
+     * no further and are not included in the resulting configuration. </p>
      *
      * <p> When all modules have been resolved then the resulting dependency
      * graph is checked to ensure that it does not contain cycles. A
-     * readability graph is constructed and then, in conjunction with the
-     * module exports and service use, checked for consistency. </p>
+     * readability graph is constructed and in conjunction with the module
+     * exports and service use, checked for consistency. </p>
      *
      * <p> Resolution and the (post-resolution) consistency checks may fail for
      * following reasons: </p>
@@ -262,6 +373,8 @@
      *
      * @param  before
      *         The <em>before</em> module finder to find modules
+     * @param  parents
+     *         The list parent configurations in search order
      * @param  after
      *         The <em>after</em> module finder to locate modules when not
      *         located by the {@code before} module finder or in parent
@@ -274,31 +387,37 @@
      *         root modules
      *
      * @throws ResolutionException
-     *         If resolution or the post-resolution checks fail for any of the
-     *         reasons listed
+     *         If resolution or the post-resolution checks fail
+     * @throws IllegalArgumentException
+     *         If the list of parents is empty
      * @throws SecurityException
      *         If locating a module is denied by the security manager
      */
-    public Configuration resolveRequires(ModuleFinder before,
-                                         ModuleFinder after,
-                                         Collection<String> roots)
+    public static Configuration resolveRequires(ModuleFinder before,
+                                                List<Configuration> parents,
+                                                ModuleFinder after,
+                                                Collection<String> roots)
     {
         Objects.requireNonNull(before);
         Objects.requireNonNull(after);
         Objects.requireNonNull(roots);
 
-        Resolver resolver = new Resolver(before, this, after, null);
+        List<Configuration> parentList = new ArrayList<>(parents);
+        if (parentList.isEmpty())
+            throw new IllegalArgumentException("'parents' is empty");
+
+        Resolver resolver = new Resolver(before, parentList, after, null);
         resolver.resolveRequires(roots);
 
-        return new Configuration(this, resolver, true);
+        return new Configuration(parentList, resolver, true);
     }
 
-
     /**
-     * Resolves a collection of root modules, with service binding, and with
-     * this configuration as its parent, to create a new configuration.
+     * Resolves a collection of root modules, with service binding, to create
+     * configuration.
      *
-     * <p> This method works exactly as specified by {@link #resolveRequires
+     * <p> This method works exactly as specified by {@link
+     * #resolveRequires(ModuleFinder,List,ModuleFinder,Collection)
      * resolveRequires} except that the graph of resolved modules is augmented
      * with modules induced by the service-use dependence relation. </p>
      *
@@ -319,6 +438,8 @@
      *
      * @param  before
      *         The <em>before</em> module finder to find modules
+     * @param  parents
+     *         The list parent configurations in search order
      * @param  after
      *         The <em>after</em> module finder to locate modules when not
      *         located by the {@code before} module finder or in parent
@@ -331,51 +452,35 @@
      *         root modules
      *
      * @throws ResolutionException
-     *         If resolution or the post-resolution checks fail for any of the
-     *         reasons listed
+     *         If resolution or the post-resolution checks fail
+     * @throws IllegalArgumentException
+     *         If the list of parents is empty
      * @throws SecurityException
      *         If locating a module is denied by the security manager
      */
-    public Configuration resolveRequiresAndUses(ModuleFinder before,
-                                                ModuleFinder after,
-                                                Collection<String> roots)
+    public static Configuration resolveRequiresAndUses(ModuleFinder before,
+                                                       List<Configuration> parents,
+                                                       ModuleFinder after,
+                                                       Collection<String> roots)
     {
         Objects.requireNonNull(before);
         Objects.requireNonNull(after);
         Objects.requireNonNull(roots);
 
-        Resolver resolver = new Resolver(before, this, after, null);
+        List<Configuration> parentList = new ArrayList<>(parents);
+        if (parentList.isEmpty())
+            throw new IllegalArgumentException("'parents' is empty");
+
+        Resolver resolver = new Resolver(before, parentList, after, null);
         resolver.resolveRequires(roots).resolveUses();
 
-        return new Configuration(this, resolver, true);
+        return new Configuration(parentList, resolver, true);
     }
 
 
     /**
-     * Resolves a collection of root modules, with service binding, and with
-     * the empty configuration as its parent. The post resolution checks
-     * are optionally run.
-     *
-     * This method is used to create the configuration for the boot layer.
-     */
-    static Configuration resolveRequiresAndUses(ModuleFinder finder,
-                                                Collection<String> roots,
-                                                boolean check,
-                                                PrintStream traceOutput)
-    {
-        Configuration parent = empty();
-
-        Resolver resolver
-            = new Resolver(finder, parent, ModuleFinder.of(), traceOutput);
-        resolver.resolveRequires(roots).resolveUses();
-
-        return new Configuration(parent, resolver, check);
-    }
-
-
-    /**
-     * Returns the <em>empty</em> configuration. The empty configuration does
-     * not contain any modules and does not have a parent.
+     * Returns the <em>empty</em> configuration. There are no modules in the
+     * empty configuration. It has no parents.
      *
      * @return The empty configuration
      */
@@ -385,13 +490,14 @@
 
 
     /**
-     * Returns this configuration's parent unless this is the {@linkplain #empty
-     * empty configuration}, which has no parent.
+     * Returns an unmodifiable list of this configuration's parents, in search
+     * order. If this is the {@linkplain #empty empty configuration} then an
+     * empty list is returned.
      *
-     * @return This configuration's parent
+     * @return A possibly-empty unmodifiable list of this parent configurations
      */
-    public Optional<Configuration> parent() {
-        return Optional.ofNullable(parent);
+    public List<Configuration> parents() {
+        return parents;
     }
 
 
@@ -408,23 +514,35 @@
 
     /**
      * Finds a resolved module in this configuration, or if not in this
-     * configuration, the {@linkplain #parent parent} configurations.
+     * configuration, the {@linkplain #parents parent} configurations.
+     * Finding a module in parent configurations is equivalent to invoking
+     * {@code findModule} on each parent, in search order, until the module
+     * is found or all parents have been searched. In a <em>tree of
+     * configurations</em> then this is equivalent to a depth-first search.
      *
      * @param  name
      *         The module name of the resolved module to find
      *
      * @return The resolved module with the given name or an empty {@code
      *         Optional} if there isn't a module with this name in this
-     *         configuration or any parent configuration
+     *         configuration or any parent configurations
      */
     public Optional<ResolvedModule> findModule(String name) {
         Objects.requireNonNull(name);
-        if (parent == null)
-            return Optional.empty();
         ResolvedModule m = nameToModule.get(name);
         if (m != null)
             return Optional.of(m);
-        return parent().flatMap(x -> x.findModule(name));
+
+        if (!parents.isEmpty()) {
+            return configurations()
+                    .skip(1)  // skip this configuration
+                    .map(cf -> cf.nameToModule)
+                    .filter(map -> map.containsKey(name))
+                    .map(map -> map.get(name))
+                    .findFirst();
+        }
+
+        return Optional.empty();
     }
 
 
@@ -444,9 +562,46 @@
     }
 
     /**
+     * Returns an ordered stream of configurations. The first element is this
+     * configuration, the remaining elements are the parent configurations
+     * in DFS order.
+     *
+     * @implNote For now, the assumption is that the number of elements will
+     * be very low and so this method does not use a specialized spliterator.
+     */
+    Stream<Configuration> configurations() {
+        List<Configuration> allConfigurations = this.allConfigurations;
+        if (allConfigurations == null) {
+            allConfigurations = new ArrayList<>();
+            Set<Configuration> visited = new HashSet<>();
+            Deque<Configuration> stack = new ArrayDeque<>();
+            visited.add(this);
+            stack.push(this);
+            while (!stack.isEmpty()) {
+                Configuration layer = stack.pop();
+                allConfigurations.add(layer);
+
+                // push in reverse order
+                for (int i = layer.parents.size() - 1; i >= 0; i--) {
+                    Configuration parent = layer.parents.get(i);
+                    if (!visited.contains(parent)) {
+                        visited.add(parent);
+                        stack.push(parent);
+                    }
+                }
+            }
+            this.allConfigurations = Collections.unmodifiableList(allConfigurations);
+        }
+        return allConfigurations.stream();
+    }
+
+    private volatile List<Configuration> allConfigurations;
+
+
+    /**
      * Returns a string describing this configuration.
      *
-     * @return A string describing this configuration
+     * @return A possibly empty string describing this configuration
      */
     @Override
     public String toString() {
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
index 60aeea6..b527ffa 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
@@ -45,6 +45,8 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static jdk.internal.module.Checks.*;
 import static java.util.Objects.*;
@@ -57,9 +59,11 @@
  * A module descriptor.
  *
  * <p> A {@code ModuleDescriptor} is typically created from the binary form
- * of a module declaration. The associated {@link ModuleDescriptor.Builder}
- * class can also be used to create a {@code ModuleDescriptor} from its
- * components. </p>
+ * of a module declaration. Alternatively, the {@link ModuleDescriptor.Builder}
+ * class can be used to create a {@code ModuleDescriptor} from its components.
+ * The {@link #module module}, {@link #openModule openModule}, and {@link
+ * #automaticModule automaticModule} methods create builders for building
+ * different kinds of modules. </p>
  *
  * <p> {@code ModuleDescriptor} objects are immutable and safe for use by
  * multiple concurrent threads.</p>
@@ -95,7 +99,13 @@
              * module</i> to have an implicitly declared dependence on the module
              * named by the {@code Requires}.
              */
-            PUBLIC,
+            TRANSITIVE,
+
+            /**
+             * The dependence is mandatory in the static phase, during compilation,
+             * but is optional in the dynamic phase, during execution.
+             */
+            STATIC,
 
             /**
              * The dependence was not explicitly or implicitly declared in the
@@ -115,16 +125,18 @@
         private final String name;
 
         private Requires(Set<Modifier> ms, String mn) {
-            this(ms, mn, true);
-        }
-        private Requires(Set<Modifier> ms, String mn, boolean check) {
-            if (ms == null || ms.isEmpty()) {
-                mods = Collections.emptySet();
+            if (ms.isEmpty()) {
+                ms = Collections.emptySet();
             } else {
-                mods = check ? Collections.unmodifiableSet(EnumSet.copyOf(ms))
-                             : ms;
+                ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
             }
-            this.name = check ? requireModuleName(mn) : mn;
+            this.mods = ms;
+            this.name = mn;
+        }
+
+        private Requires(Set<Modifier> ms, String mn, boolean unused) {
+            this.mods = ms;
+            this.name = mn;
         }
 
         /**
@@ -223,9 +235,8 @@
          */
         @Override
         public String toString() {
-            return Dependence.toString(mods, name);
+            return ModuleDescriptor.toString(mods, name);
         }
-
     }
 
 
@@ -239,36 +250,61 @@
 
     public final static class Exports {
 
+        /**
+         * A modifier on a module export.
+         *
+         * @since 9
+         */
+        public static enum Modifier {
+
+            /**
+             * The export was not explicitly or implicitly declared in the
+             * source of the module declaration.
+             */
+            SYNTHETIC,
+
+            /**
+             * The export was implicitly declared in the source of the module
+             * declaration.
+             */
+            MANDATED;
+
+        }
+
+        private final Set<Modifier> mods;
         private final String source;
         private final Set<String> targets;  // empty if unqualified export
 
         /**
-         * Constructs a qualified export.
+         * Constructs an export
          */
-        private Exports(String source, Set<String> targets) {
-            this(source, targets, true);
+        private Exports(Set<Modifier> ms, String source, Set<String> targets) {
+            if (ms.isEmpty()) {
+                ms = Collections.emptySet();
+            } else {
+                ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
+            }
+            this.mods = ms;
+            this.source = source;
+            this.targets = emptyOrUnmodifiableSet(targets);
         }
 
-        private Exports(String source, Set<String> targets, boolean check) {
-            this.source = check ? requirePackageName(source) : source;
-            targets = check ? Collections.unmodifiableSet(new HashSet<>(targets))
-                            : Collections.unmodifiableSet(targets);
-            if (targets.isEmpty())
-                throw new IllegalArgumentException("Empty target set");
-            if (check)
-                targets.stream().forEach(Checks::requireModuleName);
+        private Exports(Set<Modifier> ms,
+                        String source,
+                        Set<String> targets,
+                        boolean unused) {
+            this.mods = ms;
+            this.source = source;
             this.targets = targets;
         }
 
         /**
-         * Constructs an unqualified export.
+         * Returns the set of modifiers.
+         *
+         * @return A possibly-empty unmodifiable set of modifiers
          */
-        private Exports(String source) {
-            this(source, true);
-        }
-        private Exports(String source, boolean check) {
-            this.source = check ? requirePackageName(source) : source;
-            this.targets = Collections.emptySet();
+        public Set<Modifier> modifiers() {
+            return mods;
         }
 
         /**
@@ -304,25 +340,27 @@
         /**
          * Computes a hash code for this module export.
          *
-         * <p> The hash code is based upon the package name, and for a
-         * qualified export, the set of modules names to which the package
-         * is exported. It satisfies the general contract of the {@link
-         * Object#hashCode Object.hashCode} method.
+         * <p> The hash code is based upon the modifiers, the package name,
+         * and for a qualified export, the set of modules names to which the
+         * package is exported. It satisfies the general contract of the
+         * {@link Object#hashCode Object.hashCode} method.
          *
          * @return The hash-code value for this module export
          */
         @Override
         public int hashCode() {
-            return hash(source, targets);
+            int hash = mods.hashCode();
+            hash = hash * 43 + source.hashCode();
+            return hash * 43 + targets.hashCode();
         }
 
         /**
          * Tests this module export for equality with the given object.
          *
          * <p> If the given object is not an {@code Exports} then this method
-         * returns {@code false}. Two module exports objects are equal if the
-         * package names are equal and the set of target module names is equal.
-         * </p>
+         * returns {@code false}. Two module exports objects are equal if their
+         * set of modifiers is equal, the package names are equal and the set
+         * of target module names is equal. </p>
          *
          * <p> This method satisfies the general contract of the {@link
          * java.lang.Object#equals(Object) Object.equals} method. </p>
@@ -338,8 +376,9 @@
             if (!(ob instanceof Exports))
                 return false;
             Exports other = (Exports)ob;
-            return Objects.equals(this.source, other.source) &&
-                Objects.equals(this.targets, other.targets);
+            return Objects.equals(this.mods, other.mods)
+                    && Objects.equals(this.source, other.source)
+                    && Objects.equals(this.targets, other.targets);
         }
 
         /**
@@ -349,15 +388,177 @@
          */
         @Override
         public String toString() {
+            String s = ModuleDescriptor.toString(mods, source);
             if (targets.isEmpty())
-                return source;
+                return s;
             else
-                return source + " to " + targets;
+                return s + " to " + targets;
         }
-
     }
 
-
+
+    /**
+     * <p> Represents a module <em>opens</em> directive, may be qualified or
+     * unqualified. </p>
+     *
+     * <p> The <em>opens</em> directive in a module declaration declares a
+     * package to be open to allow all types in the package, and all their
+     * members, not just public types and their public members to be reflected
+     * on by APIs that support private access or a way to bypass or suppress
+     * default Java language access control checks. </p>
+     *
+     * @see ModuleDescriptor#opens()
+     * @since 9
+     */
+
+    public final static class Opens {
+
+        /**
+         * A modifier on a module <em>opens</em> directive.
+         *
+         * @since 9
+         */
+        public static enum Modifier {
+
+            /**
+             * The opens was not explicitly or implicitly declared in the
+             * source of the module declaration.
+             */
+            SYNTHETIC,
+
+            /**
+             * The opens was implicitly declared in the source of the module
+             * declaration.
+             */
+            MANDATED;
+
+        }
+
+        private final Set<Modifier> mods;
+        private final String source;
+        private final Set<String> targets;  // empty if unqualified export
+
+        /**
+         * Constructs an Opens
+         */
+        private Opens(Set<Modifier> ms, String source, Set<String> targets) {
+            if (ms.isEmpty()) {
+                ms = Collections.emptySet();
+            } else {
+                ms = Collections.unmodifiableSet(EnumSet.copyOf(ms));
+            }
+            this.mods = ms;
+            this.source = source;
+            this.targets = emptyOrUnmodifiableSet(targets);
+        }
+
+        private Opens(Set<Modifier> ms,
+                      String source,
+                      Set<String> targets,
+                      boolean unused) {
+            this.mods = ms;
+            this.source = source;
+            this.targets = targets;
+        }
+
+        /**
+         * Returns the set of modifiers.
+         *
+         * @return A possibly-empty unmodifiable set of modifiers
+         */
+        public Set<Modifier> modifiers() {
+            return mods;
+        }
+
+        /**
+         * Returns {@code true} if this is a qualified opens.
+         *
+         * @return {@code true} if this is a qualified opens
+         */
+        public boolean isQualified() {
+            return !targets.isEmpty();
+        }
+
+        /**
+         * Returns the package name.
+         *
+         * @return The package name
+         */
+        public String source() {
+            return source;
+        }
+
+        /**
+         * For a qualified opens, returns the non-empty and immutable set
+         * of the module names to which the package is open. For an
+         * unqualified opens, returns an empty set.
+         *
+         * @return The set of target module names or for an unqualified
+         *         opens, an empty set
+         */
+        public Set<String> targets() {
+            return targets;
+        }
+
+        /**
+         * Computes a hash code for this module opens.
+         *
+         * <p> The hash code is based upon the modifiers, the package name,
+         * and for a qualified opens, the set of modules names to which the
+         * package is opened. It satisfies the general contract of the
+         * {@link Object#hashCode Object.hashCode} method.
+         *
+         * @return The hash-code value for this module opens
+         */
+        @Override
+        public int hashCode() {
+            int hash = mods.hashCode();
+            hash = hash * 43 + source.hashCode();
+            return hash * 43 + targets.hashCode();
+        }
+
+        /**
+         * Tests this module opens for equality with the given object.
+         *
+         * <p> If the given object is not an {@code Opens} then this method
+         * returns {@code false}. Two {@code Opens} objects are equal if their
+         * set of modifiers is equal, the package names are equal and the set
+         * of target module names is equal. </p>
+         *
+         * <p> This method satisfies the general contract of the {@link
+         * java.lang.Object#equals(Object) Object.equals} method. </p>
+         *
+         * @param   ob
+         *          the object to which this object is to be compared
+         *
+         * @return  {@code true} if, and only if, the given object is a module
+         *          dependence that is equal to this module dependence
+         */
+        @Override
+        public boolean equals(Object ob) {
+            if (!(ob instanceof Opens))
+                return false;
+            Opens other = (Opens)ob;
+            return Objects.equals(this.mods, other.mods)
+                    && Objects.equals(this.source, other.source)
+                    && Objects.equals(this.targets, other.targets);
+        }
+
+        /**
+         * Returns a string describing module opens.
+         *
+         * @return A string describing module opens
+         */
+        @Override
+        public String toString() {
+            String s = ModuleDescriptor.toString(mods, source);
+            if (targets.isEmpty())
+                return s;
+            else
+                return s + " to " + targets;
+        }
+    }
+
 
     /**
      * <p> A service that a module provides one or more implementations of. </p>
@@ -369,21 +570,15 @@
     public final static class Provides {
 
         private final String service;
-        private final Set<String> providers;
+        private final List<String> providers;
 
-        private Provides(String service, Set<String> providers) {
-            this(service, providers, true);
+        private Provides(String service, List<String> providers) {
+            this.service = service;
+            this.providers = Collections.unmodifiableList(providers);
         }
 
-        private Provides(String service, Set<String> providers, boolean check) {
-            this.service = check ? requireServiceTypeName(service) : service;
-            providers = check
-                ? Collections.unmodifiableSet(new LinkedHashSet<>(providers))
-                : Collections.unmodifiableSet(providers);
-            if (providers.isEmpty())
-                throw new IllegalArgumentException("Empty providers set");
-            if (check)
-                providers.forEach(Checks::requireServiceProviderName);
+        private Provides(String service, List<String> providers, boolean unused) {
+            this.service = service;
             this.providers = providers;
         }
 
@@ -395,12 +590,13 @@
         public String service() { return service; }
 
         /**
-         * Returns the set of the fully qualified class names of the providers.
+         * Returns the list of the fully qualified class names of the providers
+         * or provider factories.
          *
-         * @return A non-empty and unmodifiable set of the fully qualified class
-         *         names of the providers.
+         * @return A non-empty and unmodifiable list of the fully qualified class
+         *         names of the providers or provider factories
          */
-        public Set<String> providers() { return providers; }
+        public List<String> providers() { return providers; }
 
         /**
          * Computes a hash code for this provides.
@@ -413,7 +609,7 @@
          */
         @Override
         public int hashCode() {
-            return hash(service, providers);
+            return service.hashCode() * 43 + providers.hashCode();
         }
 
         /**
@@ -421,7 +617,7 @@
          *
          * <p> If the given object is not a {@code Provides} then this method
          * returns {@code false}. Two {@code Provides} objects are equal if the
-         * service type is equal and the set of providers is equal. </p>
+         * service type is equal and the list of providers is equal. </p>
          *
          * <p> This method satisfies the general contract of the {@link
          * java.lang.Object#equals(Object) Object.equals} method. </p>
@@ -774,10 +970,7 @@
 
     // From module declarations
     private final String name;
-    private final Set<Requires> requires;
-    private final Set<Exports> exports;
-    private final Set<String> uses;
-    private final Map<String, Provides> provides;
+    private final boolean open;
 
     // Indicates if synthesised for a JAR file found on the module path
     private final boolean automatic;
@@ -785,6 +978,12 @@
     // Not generated from a module-info.java
     private final boolean synthetic;
 
+    private final Set<Requires> requires;
+    private final Set<Exports> exports;
+    private final Set<Opens> opens;
+    private final Set<String> uses;
+    private final Set<Provides> provides;
+
     // "Extended" information, added post-compilation by tools
     private final Version version;
     private final String mainClass;
@@ -796,12 +995,14 @@
 
 
     private ModuleDescriptor(String name,
+                             boolean open,
                              boolean automatic,
                              boolean synthetic,
-                             Map<String, Requires> requires,
+                             Set<Requires> requires,
+                             Set<Exports> exports,
+                             Set<Opens> opens,
                              Set<String> uses,
-                             Map<String, Exports> exports,
-                             Map<String, Provides> provides,
+                             Set<Provides> provides,
                              Version version,
                              String mainClass,
                              String osName,
@@ -812,31 +1013,24 @@
     {
 
         this.name = name;
+        this.open = open;
         this.automatic = automatic;
         this.synthetic = synthetic;
 
-        Set<Requires> rqs = new HashSet<>(requires.values());
-        assert (rqs.stream().map(Requires::name).sorted().distinct().count()
-                == rqs.size())
-            : "Module " + name + " has duplicate requires";
-        this.requires = emptyOrUnmodifiableSet(rqs);
+        assert (requires.stream().map(Requires::name).distinct().count()
+                == requires.size());
+        this.requires = emptyOrUnmodifiableSet(requires);
 
-        Set<Exports> exs = new HashSet<>(exports.values());
-        assert (exs.stream().map(Exports::source).sorted().distinct().count()
-                == exs.size())
-            : "Module " + name + " has duplicate exports";
-        this.exports = emptyOrUnmodifiableSet(exs);
-
+        this.exports = emptyOrUnmodifiableSet(exports);
+        this.opens = emptyOrUnmodifiableSet(opens);
         this.uses = emptyOrUnmodifiableSet(uses);
-        this.provides = emptyOrUnmodifiableMap(provides);
-
+        this.provides = emptyOrUnmodifiableSet(provides);
         this.version = version;
         this.mainClass = mainClass;
         this.osName = osName;
         this.osArch = osArch;
         this.osVersion = osVersion;
         this.hashes = hashes;
-
         this.packages = emptyOrUnmodifiableSet(packages);
     }
 
@@ -845,11 +1039,13 @@
      */
     ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) {
         this.name = md.name;
+        this.open = md.open;
         this.automatic = md.automatic;
         this.synthetic = md.synthetic;
 
         this.requires = md.requires;
         this.exports = md.exports;
+        this.opens = md.opens;
         this.uses = md.uses;
         this.provides = md.provides;
 
@@ -866,38 +1062,44 @@
     }
 
     /**
-     * Creates a module descriptor from its components. This method is intended
-     * for use by the jlink plugin.
+     * Creates a module descriptor from its components.
+     * The arguments are pre-validated and sets are unmodifiable sets.
      */
     ModuleDescriptor(String name,
+                     boolean open,
                      boolean automatic,
                      boolean synthetic,
                      Set<Requires> requires,
-                     Set<String> uses,
                      Set<Exports> exports,
-                     Map<String, Provides> provides,
+                     Set<Opens> opens,
+                     Set<String> uses,
+                     Set<Provides> provides,
                      Version version,
                      String mainClass,
                      String osName,
                      String osArch,
                      String osVersion,
                      Set<String> packages,
-                     ModuleHashes hashes) {
+                     ModuleHashes hashes,
+                     int hashCode,
+                     boolean unused) {
         this.name = name;
+        this.open = open;
         this.automatic = automatic;
         this.synthetic = synthetic;
-        this.requires = Collections.unmodifiableSet(requires);
-        this.exports = Collections.unmodifiableSet(exports);
-        this.uses = Collections.unmodifiableSet(uses);
-        this.provides = Collections.unmodifiableMap(provides);
-        this.packages = Collections.unmodifiableSet(packages);
-
+        this.requires = requires;
+        this.exports = exports;
+        this.opens = opens;
+        this.uses = uses;
+        this.provides = provides;
+        this.packages = packages;
         this.version = version;
         this.mainClass = mainClass;
         this.osName = osName;
         this.osArch = osArch;
         this.osVersion = osVersion;
         this.hashes = hashes;
+        this.hash = hashCode;
     }
 
     /**
@@ -910,6 +1112,19 @@
     }
 
     /**
+     * <p> Returns {@code true} if this is an open module. </p>
+     *
+     * <p> An open module does not declare any open packages (the {@link #opens()
+     * opens} method returns an empty set) but the resulting module is treated
+     * as if all packages are open. </p>
+     *
+     * @return  {@code true} if this is an open module
+     */
+    public boolean isOpen() {
+        return open;
+    }
+
+    /**
      * <p> Returns {@code true} if this is an automatic module. </p>
      *
      * <p> An automatic module is defined implicitly rather than explicitly
@@ -933,8 +1148,6 @@
      *
      * @return  {@code true} if this module descriptor was not generated by
      *          an explicit or implicit module declaration
-     *
-     * @jvms 4.7.8 The {@code Synthetic} Attribute
      */
     public boolean isSynthetic() {
         return synthetic;
@@ -950,6 +1163,33 @@
     }
 
     /**
+     * <p> The module exports. </p>
+     *
+     * @return  A possibly-empty unmodifiable set of exported packages
+     */
+    public Set<Exports> exports() {
+        return exports;
+    }
+
+    /**
+     * <p> The module <em>opens</em> directives. </p>
+     *
+     * <p> Each {@code Opens} object in the set represents a package (and
+     * the set of target module names when qualified) where all types in the
+     * package, and all their members, not just public types and their public
+     * members, can be reflected on when using APIs that bypass or suppress
+     * default Java language access control checks. </p>
+     *
+     * <p> This method returns an empty set when invoked on {@link #isOpen()
+     * open} module. </p>
+     *
+     * @return  A possibly-empty unmodifiable set of open packages
+     */
+    public Set<Opens> opens() {
+        return opens;
+    }
+
+    /**
      * <p> The service dependences of this module. </p>
      *
      * @return  A possibly-empty unmodifiable set of the fully qualified class
@@ -962,24 +1202,14 @@
     /**
      * <p> The services that this module provides. </p>
      *
-     * @return The possibly-empty unmodifiable map of the services that this
-     *         module provides. The map key is fully qualified class name of
-     *         the service type.
+     * @return The possibly-empty unmodifiable set of the services that this
+     *         module provides
      */
-    public Map<String, Provides> provides() {
+    public Set<Provides> provides() {
         return provides;
     }
 
     /**
-     * <p> The module exports. </p>
-     *
-     * @return  A possibly-empty unmodifiable set of exported packages
-     */
-    public Set<Exports> exports() {
-        return exports;
-    }
-
-    /**
      * Returns this module's version.
      *
      * @return This module's version
@@ -1046,22 +1276,9 @@
     }
 
     /**
-     * Returns the names of the packages defined in, but not exported by, this
-     * module.
+     * Returns the names of all packages in this module.
      *
-     * @return A possibly-empty unmodifiable set of the concealed packages
-     */
-    public Set<String> conceals() {
-        Set<String> conceals = new HashSet<>(packages);
-        exports.stream().map(Exports::source).forEach(conceals::remove);
-        return emptyOrUnmodifiableSet(conceals);
-    }
-
-    /**
-     * Returns the names of all the packages defined in this module, whether
-     * exported or concealed.
-     *
-     * @return A possibly-empty unmodifiable set of the all packages
+     * @return A possibly-empty unmodifiable set of all packages in the module
      */
     public Set<String> packages() {
         return packages;
@@ -1078,31 +1295,39 @@
     /**
      * A builder used for building {@link ModuleDescriptor} objects.
      *
-     * <p> Example usage: </p>
+     * <p> {@code ModuleDescriptor} defines the {@link #module module}, {@link
+     * #openModule openModule}, and {@link #automaticModule automaticModule}
+     * methods to create builders for building different kinds of modules. </p>
      *
-     * <pre>{@code
-     *     ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1")
-     *         .requires("m2")
+     * <p> Example usage: </p>
+     * <pre>{@code    ModuleDescriptor descriptor = ModuleDescriptor.module("m1")
      *         .exports("p")
+     *         .requires("m2")
      *         .build();
      * }</pre>
      *
-     * @apiNote A {@code Builder} cannot be used to create an {@link
-     * ModuleDescriptor#isAutomatic() automatic} or a {@link
-     * ModuleDescriptor#isSynthetic() synthetic} module.
+     * @apiNote A {@code Builder} checks the components and invariants as
+     * components are added to the builder. The rational for this is to detect
+     * errors as early as possible and not defer all validation to the
+     * {@link #build build} method. A {@code Builder} cannot be used to create
+     * a {@link ModuleDescriptor#isSynthetic() synthetic} module.
      *
      * @since 9
      */
     public static final class Builder {
-
         final String name;
+        final boolean strict; // true if module names are checked
+        boolean open;
         boolean automatic;
         boolean synthetic;
         final Map<String, Requires> requires = new HashMap<>();
-        final Set<String> uses = new HashSet<>();
+
         final Map<String, Exports> exports = new HashMap<>();
+        final Map<String, Opens> opens = new HashMap<>();
+        final Set<String> concealedPackages = new HashSet<>();
+
+        final Set<String> uses = new HashSet<>();
         final Map<String, Provides> provides = new HashMap<>();
-        Set<String> conceals = Collections.emptySet();
         Version version;
         String osName;
         String osArch;
@@ -1113,29 +1338,30 @@
         /**
          * Initializes a new builder with the given module name.
          *
-         * @param  name
-         *         The module name
-         *
-         * @throws IllegalArgumentException
-         *         If the module name is {@code null} or is not a legal Java
-         *         identifier
+         * @param strict
+         *        Indicates whether module names are checked or not
          */
-        public Builder(String name) {
-            this.name = requireModuleName(name);
+        Builder(String name, boolean strict) {
+            this.strict = strict;
+            this.name = (strict) ? requireModuleName(name) : name;
         }
 
-        /**
-         * Updates the builder so that it builds an automatic module.
-         *
-         * @return This builder
-         *
-         * @see ModuleDescriptor#isAutomatic()
-         */
-        /* package */ Builder automatic() {
-            this.automatic = true;
+        /* package */ Builder open(boolean open) {
+            this.open = open;
             return this;
         }
 
+        /* package */ Builder automatic(boolean automatic) {
+            this.automatic = automatic;
+            return this;
+        }
+
+        /* package */ boolean isOpen() { return open; }
+
+        /* package */ boolean isAutomatic() {
+            return automatic;
+        }
+
         /**
          * Adds a dependence on a module.
          *
@@ -1165,7 +1391,7 @@
          * Adds a dependence on a module with the given (and possibly empty)
          * set of modifiers.
          *
-         * @param  mods
+         * @param  ms
          *         The set of modifiers
          * @param  mn
          *         The module name
@@ -1179,14 +1405,10 @@
          * @throws IllegalStateException
          *         If the dependence on the module has already been declared
          */
-        public Builder requires(Set<Requires.Modifier> mods, String mn) {
-            if (name.equals(mn))
-                throw new IllegalArgumentException("Dependence on self");
-            if (requires.containsKey(mn))
-                throw new IllegalStateException("Dependence upon " + mn
-                                                + " already declared");
-            requires.put(mn, new Requires(mods, mn)); // checks mn
-            return this;
+        public Builder requires(Set<Requires.Modifier> ms, String mn) {
+            if (strict)
+                mn = requireModuleName(mn);
+            return requires(new Requires(ms, mn));
         }
 
         /**
@@ -1209,62 +1431,6 @@
         }
 
         /**
-         * Adds a dependence on a module with the given modifier.
-         *
-         * @param  mod
-         *         The modifier
-         * @param  mn
-         *         The module name
-         *
-         * @return This builder
-         *
-         * @throws IllegalArgumentException
-         *         If the module name is {@code null}, is not a legal Java
-         *         identifier, or is equal to the module name that this builder
-         *         was initialized to build
-         * @throws IllegalStateException
-         *         If the dependence on the module has already been declared
-         */
-        public Builder requires(Requires.Modifier mod, String mn) {
-            return requires(EnumSet.of(mod), mn);
-        }
-
-        /**
-         * Adds a service dependence.
-         *
-         * @param  st
-         *         The service type
-         *
-         * @return This builder
-         *
-         * @throws IllegalArgumentException
-         *         If the service type is {@code null} or is not a legal Java
-         *         identifier
-         * @throws IllegalStateException
-         *         If a dependency on the service type has already been declared
-         */
-        public Builder uses(String st) {
-            if (uses.contains(requireServiceTypeName(st)))
-                throw new IllegalStateException("Dependence upon service "
-                                                + st + " already declared");
-            uses.add(st);
-            return this;
-        }
-
-        /**
-         * Ensures that the given package name has not been declared as an
-         * exported or concealed package.
-         */
-        private void ensureNotExportedOrConcealed(String pn) {
-            if (exports.containsKey(pn))
-                throw new IllegalStateException("Export of package "
-                                                + pn + " already declared");
-            if (conceals.contains(pn))
-                throw new IllegalStateException("Concealed package "
-                                                + pn + " already declared");
-        }
-
-        /**
          * Adds an export.
          *
          * @param  e
@@ -1273,18 +1439,90 @@
          * @return This builder
          *
          * @throws IllegalStateException
-         *         If the package is already declared as an exported or
-         *         concealed package
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method or the package is already
+         *         declared as exported
          */
         public Builder exports(Exports e) {
-            String pn = e.source();
-            ensureNotExportedOrConcealed(pn);
-            exports.put(pn, e);
+            // can't be exported and concealed
+            String source = e.source();
+            if (concealedPackages.contains(source)) {
+                throw new IllegalStateException("Package " + source
+                                                 + " already declared");
+            }
+            if (exports.containsKey(source)) {
+                throw new IllegalStateException("Exported package " + source
+                                                 + " already declared");
+            }
+
+            exports.put(source, e);
             return this;
         }
 
         /**
-         * Adds an export to a set of target modules.
+         * Adds an export, with the given (and possibly empty) set of modifiers,
+         * to export a package to a set of target modules.
+         *
+         * @param  ms
+         *         The set of modifiers
+         * @param  pn
+         *         The package name
+         * @param  targets
+         *         The set of target modules names
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the package name or any of the target modules is {@code
+         *         null} or is not a legal Java identifier, or the set of
+         *         targets is empty
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method or the package is already
+         *         declared as exported
+         */
+        public Builder exports(Set<Exports.Modifier> ms,
+                               String pn,
+                               Set<String> targets)
+        {
+            Exports e = new Exports(ms, requirePackageName(pn), targets);
+
+            // check targets
+            targets = e.targets();
+            if (targets.isEmpty())
+                throw new IllegalArgumentException("Empty target set");
+            if (strict)
+                targets.stream().forEach(Checks::requireModuleName);
+
+            return exports(e);
+        }
+
+        /**
+         * Adds an unqualified export with the given (and possibly empty) set
+         * of modifiers.
+         *
+         * @param  ms
+         *         The set of modifiers
+         * @param  pn
+         *         The package name
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the package name is {@code null} or is not a legal Java
+         *         identifier
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method or the package is already
+         *         declared as exported
+         */
+        public Builder exports(Set<Exports.Modifier> ms, String pn) {
+            Exports e = new Exports(ms, requirePackageName(pn), Collections.emptySet());
+            return exports(e);
+        }
+
+        /**
+         * Adds an export to export a package to a set of target modules.
          *
          * @param  pn
          *         The package name
@@ -1298,38 +1536,16 @@
          *         null} or is not a legal Java identifier, or the set of
          *         targets is empty
          * @throws IllegalStateException
-         *         If the package is already declared as an exported or
-         *         concealed package
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method or the package is already
+         *         declared as exported
          */
         public Builder exports(String pn, Set<String> targets) {
-            ensureNotExportedOrConcealed(pn);
-            exports.put(pn, new Exports(pn, targets)); // checks pn and targets
-            return this;
+            return exports(Collections.emptySet(), pn, targets);
         }
 
         /**
-         * Adds an export to a target module.
-         *
-         * @param  pn
-         *         The package name
-         * @param  target
-         *         The target module name
-         *
-         * @return This builder
-         *
-         * @throws IllegalArgumentException
-         *         If the package name or target module is {@code null} or is
-         *         not a legal Java identifier
-         * @throws IllegalStateException
-         *         If the package is already declared as an exported or
-         *         concealed package
-         */
-        public Builder exports(String pn, String target) {
-            return exports(pn, Collections.singleton(target));
-        }
-
-        /**
-         * Adds an export.
+         * Adds an unqualified export.
          *
          * @param  pn
          *         The package name
@@ -1340,18 +1556,186 @@
          *         If the package name is {@code null} or is not a legal Java
          *         identifier
          * @throws IllegalStateException
-         *         If the package is already declared as an exported or
-         *         concealed package
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method or the package is already
+         *         declared as exported
          */
         public Builder exports(String pn) {
-            ensureNotExportedOrConcealed(pn);
-            exports.put(pn, new Exports(pn)); // checks pn
+            return exports(Collections.emptySet(), pn);
+        }
+
+        /**
+         * Adds an <em>opens</em> directive.
+         *
+         * @param  obj
+         *         The {@code Opens} object
+         *
+         * @return This builder
+         *
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method, the package is already
+         *         declared as open, or this is a builder for an open module
+         */
+        public Builder opens(Opens obj) {
+            if (open) {
+                throw new IllegalStateException("open modules cannot declare"
+                                                + " open packages");
+            }
+
+            // can't be open and concealed
+            String source = obj.source();
+            if (concealedPackages.contains(source)) {
+                throw new IllegalStateException("Package " + source
+                                                + " already declared");
+            }
+            if (opens.containsKey(source)) {
+                throw new IllegalStateException("Open package " + source
+                                                + " already declared");
+            }
+
+            opens.put(source, obj);
             return this;
         }
 
+
+        /**
+         * Adds an <em>opens</em> directive, with the given (and possibly empty)
+         * set of modifiers, to open a package to a set of target modules.
+         *
+         * @param  ms
+         *         The set of modifiers
+         * @param  pn
+         *         The package name
+         * @param  targets
+         *         The set of target modules names
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the package name or any of the target modules is {@code
+         *         null} or is not a legal Java identifier, or the set of
+         *         targets is empty
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method, the package is already
+         *         declared as open, or this is a builder for an open module
+         */
+        public Builder opens(Set<Opens.Modifier> ms,
+                             String pn,
+                             Set<String> targets)
+        {
+            Opens e = new Opens(ms, requirePackageName(pn), targets);
+
+            // check targets
+            targets = e.targets();
+            if (targets.isEmpty())
+                throw new IllegalArgumentException("Empty target set");
+            if (strict)
+                targets.stream().forEach(Checks::requireModuleName);
+
+            return opens(e);
+        }
+
+        /**
+         * Adds an <em>opens</em> directive to open a package with the given (and
+         * possibly empty) set of modifiers.
+         *
+         * @param  ms
+         *         The set of modifiers
+         * @param  pn
+         *         The package name
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the package name is {@code null} or is not a legal Java
+         *         identifier
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method, the package is already
+         *         declared as open, or this is a builder for an open module
+         */
+        public Builder opens(Set<Opens.Modifier> ms, String pn) {
+            Opens e = new Opens(ms, requirePackageName(pn), Collections.emptySet());
+            return opens(e);
+        }
+
+        /**
+         * Adds an <em>opens</em> directive to open a package to a set of target
+         * modules.
+         *
+         * @param  pn
+         *         The package name
+         * @param  targets
+         *         The set of target modules names
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the package name or any of the target modules is {@code
+         *         null} or is not a legal Java identifier, or the set of
+         *         targets is empty
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method, the package is already
+         *         declared as open, or this is a builder for an open module
+         */
+        public Builder opens(String pn, Set<String> targets) {
+            return opens(Collections.emptySet(), pn, targets);
+        }
+
+        /**
+         * Adds an <em>opens</em> directive to open a package.
+         *
+         * @param  pn
+         *         The package name
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the package name is {@code null} or is not a legal Java
+         *         identifier
+         * @throws IllegalStateException
+         *         If the package is already declared as a package with the
+         *         {@link #contains contains} method, the package is already
+         *         declared as open, or this is a builder for an open module
+         */
+        public Builder opens(String pn) {
+            return opens(Collections.emptySet(), pn);
+        }
+
+
         // Used by ModuleInfo, after a packageFinder is invoked
-        /* package */ Set<String> exportedPackages() {
-            return exports.keySet();
+        /* package */ Set<String> exportedAndOpenPackages() {
+            if (opens.isEmpty())
+                return exports.keySet();
+            Set<String> result = new HashSet<>();
+            result.addAll(exports.keySet());
+            result.addAll(opens.keySet());
+            return result;
+        }
+
+        /**
+         * Adds a service dependence.
+         *
+         * @param  service
+         *         The service type
+         *
+         * @return This builder
+         *
+         * @throws IllegalArgumentException
+         *         If the service type is {@code null} or is not a legal Java
+         *         identifier
+         * @throws IllegalStateException
+         *         If a dependency on the service type has already been declared
+         */
+        public Builder uses(String service) {
+            if (uses.contains(requireServiceTypeName(service)))
+                throw new IllegalStateException("Dependence upon service "
+                                                + service + " already declared");
+            uses.add(service);
+            return this;
         }
 
         /**
@@ -1376,38 +1760,47 @@
         }
 
         /**
-         * Provides service {@code st} with implementations {@code pcs}.
+         * Provides implementations of a service.
          *
-         * @param  st
+         * @param  service
          *         The service type
-         * @param  pcs
-         *         The set of provider class names
+         * @param  providers
+         *         The list of provider or provider factory class names
          *
          * @return This builder
          *
          * @throws IllegalArgumentException
          *         If the service type or any of the provider class names is
-         *         {@code null} or is not a legal Java identifier, or the set
+         *         {@code null} or is not a legal Java identifier, or the list
          *         of provider class names is empty
          * @throws IllegalStateException
          *         If the providers for the service type have already been
          *         declared
          */
-        public Builder provides(String st, Set<String> pcs) {
-            if (provides.containsKey(st))
+        public Builder provides(String service, List<String> providers) {
+            if (provides.containsKey(service))
                 throw new IllegalStateException("Providers of service "
-                                                + st + " already declared");
-            provides.put(st, new Provides(st, pcs)); // checks st and pcs
+                                                + service + " already declared by " + name);
+
+            Provides p = new Provides(requireServiceTypeName(service), providers);
+
+            // check providers after the set has been copied.
+            List<String> providerNames = p.providers();
+            if (providerNames.isEmpty())
+                throw new IllegalArgumentException("Empty providers set");
+            providerNames.forEach(Checks::requireServiceProviderName);
+
+            provides.put(service, p);
             return this;
         }
 
         /**
-         * Provides service {@code st} with implementation {@code pc}.
+         * Provides an implementation of a service.
          *
-         * @param  st
+         * @param  service
          *         The service type
-         * @param  pc
-         *         The provider class name
+         * @param  provider
+         *         The provider or provider factory class name
          *
          * @return This builder
          *
@@ -1418,15 +1811,17 @@
          *         If the providers for the service type have already been
          *         declared
          */
-        public Builder provides(String st, String pc) {
-            return provides(st, Collections.singleton(pc));
+        public Builder provides(String service, String provider) {
+            if (provider == null)
+                throw new IllegalArgumentException("'provider' is null");
+            return provides(service, List.of(provider));
         }
 
         /**
-         * Adds a set of (possible empty) concealed packages.
+         * Adds a (possible empty) set of packages to the module
          *
          * @param  pns
-         *         The set of package names of the concealed packages
+         *         The set of package names
          *
          * @return This builder
          *
@@ -1434,16 +1829,17 @@
          *         If any of the package names is {@code null} or is not a
          *         legal Java identifier
          * @throws IllegalStateException
-         *         If any of packages are already declared as a concealed or
-         *         exported package
+         *         If any of packages are already declared as packages in
+         *         the module. This includes packages that are already
+         *         declared as exported or open packages.
          */
-        public Builder conceals(Set<String> pns) {
-            pns.forEach(this::conceals);
+        public Builder contains(Set<String> pns) {
+            pns.forEach(this::contains);
             return this;
         }
 
         /**
-         * Adds a concealed package.
+         * Adds a package to the module.
          *
          * @param  pn
          *         The package name
@@ -1454,15 +1850,25 @@
          *         If the package name is {@code null}, or is not a legal Java
          *         identifier
          * @throws IllegalStateException
-         *         If the package is already declared as a concealed or exported
-         *         package
+         *         If the package is already declared as a package in the
+         *         module. This includes the package already declared as an
+         *         exported or open package.
          */
-        public Builder conceals(String pn) {
+        public Builder contains(String pn) {
             Checks.requirePackageName(pn);
-            ensureNotExportedOrConcealed(pn);
-            if (conceals.isEmpty())
-                conceals = new HashSet<>();
-            conceals.add(pn);
+            if (concealedPackages.contains(pn)) {
+                throw new IllegalStateException("Package " + pn
+                                                + " already declared");
+            }
+            if (exports.containsKey(pn)) {
+                throw new IllegalStateException("Exported package "
+                                                + pn + " already declared");
+            }
+            if (opens.containsKey(pn)) {
+                throw new IllegalStateException("Open package "
+                                                 + pn + " already declared");
+            }
+            concealedPackages.add(pn);
             return this;
         }
 
@@ -1473,13 +1879,8 @@
          *         The version
          *
          * @return This builder
-         *
-         * @throws IllegalStateException
-         *         If the module version is already set
          */
         public Builder version(Version v) {
-            if (version != null)
-                throw new IllegalStateException("module version already set");
             version = requireNonNull(v);
             return this;
         }
@@ -1494,16 +1895,11 @@
          *
          * @throws IllegalArgumentException
          *         If {@code v} is null or cannot be parsed as a version string
-         * @throws IllegalStateException
-         *         If the module version is already set
          *
          * @see Version#parse(String)
          */
         public Builder version(String v) {
-            if (version != null)
-                throw new IllegalStateException("module version already set");
-            version = Version.parse(v);
-            return this;
+            return version(Version.parse(v));
         }
 
         /**
@@ -1516,12 +1912,8 @@
          *
          * @throws IllegalArgumentException
          *         If {@code mainClass} is null or is not a legal Java identifier
-         * @throws IllegalStateException
-         *         If the module main class is already set
          */
         public Builder mainClass(String mc) {
-            if (mainClass != null)
-                throw new IllegalStateException("main class already set");
             mainClass = requireJavaIdentifier("main class name", mc);
             return this;
         }
@@ -1536,12 +1928,8 @@
          *
          * @throws IllegalArgumentException
          *         If {@code name} is null or the empty String
-         * @throws IllegalStateException
-         *         If the operating system name is already set
          */
         public Builder osName(String name) {
-            if (osName != null)
-                throw new IllegalStateException("OS name already set");
             if (name == null || name.isEmpty())
                 throw new IllegalArgumentException("OS name is null or empty");
             osName = name;
@@ -1558,12 +1946,8 @@
          *
          * @throws IllegalArgumentException
          *         If {@code name} is null or the empty String
-         * @throws IllegalStateException
-         *         If the operating system architecture is already set
          */
         public Builder osArch(String arch) {
-            if (osArch != null)
-                throw new IllegalStateException("OS arch already set");
             if (arch == null || arch.isEmpty())
                 throw new IllegalArgumentException("OS arch is null or empty");
             osArch = arch;
@@ -1580,12 +1964,8 @@
          *
          * @throws IllegalArgumentException
          *         If {@code name} is null or the empty String
-         * @throws IllegalStateException
-         *         If the operating system version is already set
          */
         public Builder osVersion(String version) {
-            if (osVersion != null)
-                throw new IllegalStateException("OS version already set");
             if (version == null || version.isEmpty())
                 throw new IllegalArgumentException("OS version is null or empty");
             osVersion = version;
@@ -1597,7 +1977,6 @@
             return this;
         }
 
-
         /* package */ Builder synthetic(boolean v) {
             this.synthetic = v;
             return this;
@@ -1609,16 +1988,24 @@
          * @return The module descriptor
          */
         public ModuleDescriptor build() {
-            assert name != null;
+            Set<Requires> requires = new HashSet<>(this.requires.values());
 
-            Set<String> packages = new HashSet<>(conceals);
-            packages.addAll(exportedPackages());
+            Set<String> packages = new HashSet<>(exportedAndOpenPackages());
+            packages.addAll(concealedPackages);
+
+            Set<Exports> exports = new HashSet<>(this.exports.values());
+            Set<Opens> opens = new HashSet<>(this.opens.values());
+
+            Set<Provides> provides = new HashSet<>(this.provides.values());
+
             return new ModuleDescriptor(name,
+                                        open,
                                         automatic,
                                         synthetic,
                                         requires,
-                                        uses,
                                         exports,
+                                        opens,
+                                        uses,
                                         provides,
                                         version,
                                         mainClass,
@@ -1631,7 +2018,6 @@
 
     }
 
-
     /**
      * Compares this module descriptor to another.
      *
@@ -1689,11 +2075,13 @@
             return false;
         ModuleDescriptor that = (ModuleDescriptor)ob;
         return (name.equals(that.name)
+                && open == that.open
                 && automatic == that.automatic
                 && synthetic == that.synthetic
                 && requires.equals(that.requires)
-                && uses.equals(that.uses)
                 && exports.equals(that.exports)
+                && opens.equals(that.opens)
+                && uses.equals(that.uses)
                 && provides.equals(that.provides)
                 && Objects.equals(version, that.version)
                 && Objects.equals(mainClass, that.mainClass)
@@ -1720,11 +2108,13 @@
         int hc = hash;
         if (hc == 0) {
             hc = name.hashCode();
+            hc = hc * 43 + Boolean.hashCode(open);
             hc = hc * 43 + Boolean.hashCode(automatic);
             hc = hc * 43 + Boolean.hashCode(synthetic);
             hc = hc * 43 + requires.hashCode();
-            hc = hc * 43 + uses.hashCode();
             hc = hc * 43 + exports.hashCode();
+            hc = hc * 43 + opens.hashCode();
+            hc = hc * 43 + uses.hashCode();
             hc = hc * 43 + provides.hashCode();
             hc = hc * 43 + Objects.hashCode(version);
             hc = hc * 43 + Objects.hashCode(mainClass);
@@ -1748,36 +2138,101 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Module { name: ").append(toNameAndVersion());
+
+        if (isOpen())
+            sb.append("open ");
+        sb.append("module { name: ").append(toNameAndVersion());
         if (!requires.isEmpty())
             sb.append(", ").append(requires);
         if (!uses.isEmpty())
             sb.append(", ").append(uses);
         if (!exports.isEmpty())
             sb.append(", exports: ").append(exports);
+        if (!opens.isEmpty())
+            sb.append(", opens: ").append(opens);
         if (!provides.isEmpty()) {
-            sb.append(", provides: [");
-            for (Map.Entry<String, Provides> entry : provides.entrySet()) {
-                sb.append(entry.getKey())
-                   .append(" with ")
-                   .append(entry.getValue());
-            }
-            sb.append("]");
+            sb.append(", provides: ").append(provides);
         }
         sb.append(" }");
         return sb.toString();
     }
 
+
+    /**
+     * Instantiates a builder to build a module descriptor.
+     *
+     * @param  name
+     *         The module name
+     *
+     * @return A new builder
+     *
+     * @throws IllegalArgumentException
+     *         If the module name is {@code null} or is not a legal Java
+     *         identifier
+     */
+    public static Builder module(String name) {
+        return new Builder(name, true);
+    }
+
+    /**
+     * Instantiates a builder to build a module descriptor for an open module.
+     * An open module does not declare any open packages but the resulting
+     * module is treated as if all packages are open.
+     *
+     * <p> As an example, the following creates a module descriptor for an open
+     * name "{@code m}" containing two packages, one of which is exported. </p>
+     * <pre>{@code
+     *     ModuleDescriptor descriptor = ModuleDescriptor.openModule("m")
+     *         .requires("java.base")
+     *         .exports("p")
+     *         .contains("q")
+     *         .build();
+     * }</pre>
+     *
+     * @param  name
+     *         The module name
+     *
+     * @return A new builder that builds an open module
+     *
+     * @throws IllegalArgumentException
+     *         If the module name is {@code null} or is not a legal Java
+     *         identifier
+     */
+    public static Builder openModule(String name) {
+        return new Builder(name, true).open(true);
+    }
+
+    /**
+     * Instantiates a builder to build a module descriptor for an automatic
+     * module. Automatic modules receive special treatment during resolution
+     * (see {@link Configuration}) so that they read all other modules. When
+     * Instantiated in the Java virtual machine as a {@link java.lang.reflect.Module}
+     * then the Module reads every unnamed module in the Java virtual machine.
+     *
+     * @param  name
+     *         The module name
+     *
+     * @return A new builder that builds an automatic module
+     *
+     * @throws IllegalArgumentException
+     *         If the module name is {@code null} or is not a legal Java
+     *         identifier
+     *
+     * @see ModuleFinder#of(Path[])
+     */
+    public static Builder automaticModule(String name) {
+        return new Builder(name, true).automatic(true);
+    }
+
+
     /**
      * Reads the binary form of a module declaration from an input stream
      * as a module descriptor.
      *
      * <p> If the descriptor encoded in the input stream does not indicate a
-     * set of concealed packages then the {@code packageFinder} will be
-     * invoked.  The packages it returns, except for those indicated as
-     * exported in the encoded descriptor, will be considered to be concealed.
-     * If the {@code packageFinder} throws an {@link UncheckedIOException} then
-     * {@link IOException} cause will be re-thrown. </p>
+     * set of packages in the module then the {@code packageFinder} will be
+     * invoked. If the {@code packageFinder} throws an {@link UncheckedIOException}
+     * then {@link IOException} cause will be re-thrown. </p>
      *
      * <p> If there are bytes following the module descriptor then it is
      * implementation specific as to whether those bytes are read, ignored,
@@ -1789,12 +2244,12 @@
      *
      * @apiNote The {@code packageFinder} parameter is for use when reading
      * module descriptors from legacy module-artifact formats that do not
-     * record the set of concealed packages in the descriptor itself.
+     * record the set of packages in the descriptor itself.
      *
      * @param  in
      *         The input stream
      * @param  packageFinder
-     *         A supplier that can produce a set of package names
+     *         A supplier that can produce the set of packages
      *
      * @return The module descriptor
      *
@@ -1834,10 +2289,7 @@
      * as a module descriptor.
      *
      * <p> If the descriptor encoded in the byte buffer does not indicate a
-     * set of concealed packages then the {@code packageFinder} will be
-     * invoked.  The packages it returns, except for those indicated as
-     * exported in the encoded descriptor, will be considered to be
-     * concealed. </p>
+     * set of packages then the {@code packageFinder} will be invoked. </p>
      *
      * <p> The module descriptor is read from the buffer stating at index
      * {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
@@ -1853,12 +2305,12 @@
      *
      * @apiNote The {@code packageFinder} parameter is for use when reading
      * module descriptors from legacy module-artifact formats that do not
-     * record the set of concealed packages in the descriptor itself.
+     * record the set of packages in the descriptor itself.
      *
      * @param  bb
      *         The byte buffer
      * @param  packageFinder
-     *         A supplier that can produce a set of package names
+     *         A supplier that can produce the set of packages
      *
      * @return The module descriptor
      *
@@ -1908,6 +2360,15 @@
         }
     }
 
+    /**
+     * Returns a string containing the given set of modifiers and label.
+     */
+    private static <M> String toString(Set<M> mods, String what) {
+        return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
+                              Stream.of(what)))
+                .collect(Collectors.joining(" "));
+    }
+
     static {
         /**
          * Setup the shared secret to allow code in other packages access
@@ -1915,25 +2376,48 @@
          */
         jdk.internal.misc.SharedSecrets
             .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
+                @Override
+                public Builder newModuleBuilder(String mn, boolean strict) {
+                    return new Builder(mn, strict);
+                }
+
+                @Override
+                public Builder newOpenModuleBuilder(String mn, boolean strict) {
+                    return new Builder(mn, strict).open(true);
+                }
 
                 @Override
                 public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
-                    return new Requires(ms, mn, false);
+                    return new Requires(ms, mn, true);
                 }
 
                 @Override
-                public Exports newExports(String source, Set<String> targets) {
-                    return new Exports(source, targets, false);
+                public Exports newExports(Set<Exports.Modifier> ms, String source) {
+                    return new Exports(ms, source, Collections.emptySet(), true);
                 }
 
                 @Override
-                public Exports newExports(String source) {
-                    return new Exports(source, false);
+                public Exports newExports(Set<Exports.Modifier> ms,
+                                          String source,
+                                          Set<String> targets) {
+                    return new Exports(ms, source, targets, true);
                 }
 
                 @Override
-                public Provides newProvides(String service, Set<String> providers) {
-                    return new Provides(service, providers, false);
+                public Opens newOpens(Set<Opens.Modifier> ms,
+                                      String source,
+                                      Set<String> targets) {
+                    return new Opens(ms, source, targets, true);
+                }
+
+                @Override
+                public Opens newOpens(Set<Opens.Modifier> ms, String source) {
+                    return new Opens(ms, source, Collections.emptySet(), true);
+                }
+
+                @Override
+                public Provides newProvides(String service, List<String> providers) {
+                    return new Provides(service, providers, true);
                 }
 
                 @Override
@@ -1949,25 +2433,30 @@
 
                 @Override
                 public ModuleDescriptor newModuleDescriptor(String name,
+                                                            boolean open,
                                                             boolean automatic,
                                                             boolean synthetic,
                                                             Set<Requires> requires,
-                                                            Set<String> uses,
                                                             Set<Exports> exports,
-                                                            Map<String, Provides> provides,
+                                                            Set<Opens> opens,
+                                                            Set<String> uses,
+                                                            Set<Provides> provides,
                                                             Version version,
                                                             String mainClass,
                                                             String osName,
                                                             String osArch,
                                                             String osVersion,
                                                             Set<String> packages,
-                                                            ModuleHashes hashes) {
+                                                            ModuleHashes hashes,
+                                                            int hashCode) {
                     return new ModuleDescriptor(name,
+                                                open,
                                                 automatic,
                                                 synthetic,
                                                 requires,
-                                                uses,
                                                 exports,
+                                                opens,
+                                                uses,
                                                 provides,
                                                 version,
                                                 mainClass,
@@ -1975,7 +2464,14 @@
                                                 osArch,
                                                 osVersion,
                                                 packages,
-                                                hashes);
+                                                hashes,
+                                                hashCode,
+                                                false);
+                }
+
+                @Override
+                public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
+                    return descriptor.hashes();
                 }
 
                 @Override
@@ -1995,11 +2491,6 @@
                 }
 
                 @Override
-                public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
-                    return descriptor.hashes();
-                }
-
-                @Override
                 public ModuleFinder newModulePath(Runtime.Version version,
                                                   boolean isLinkPhase,
                                                   Path... entries) {
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
index 4e72a52..4b98bf4 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java
@@ -233,10 +233,11 @@
      *         ModuleDescriptor.Version} and ignored if it cannot be parsed as
      *         a {@code Version}. </p></li>
      *
-     *         <li><p> For the module name, then all non-alphanumeric
-     *         characters ({@code [^A-Za-z0-9])} are replaced with a dot
-     *         ({@code "."}), all repeating dots are replaced with one dot,
-     *         and all leading and trailing dots are removed. </p></li>
+     *         <li><p> For the module name, then any trailing digits and dots
+     *         are removed, all non-alphanumeric characters ({@code [^A-Za-z0-9]})
+     *         are replaced with a dot ({@code "."}), all repeating dots are
+     *         replaced with one dot, and all leading and trailing dots are
+     *         removed. </p></li>
      *
      *         <li><p> As an example, a JAR file named {@code foo-bar.jar} will
      *         derive a module name {@code foo.bar} and no version. A JAR file
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
index 1d0e22f..b1c8281 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,13 +31,17 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UncheckedIOException;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleDescriptor.Builder;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.nio.ByteBuffer;
 import java.nio.BufferUnderflowException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Supplier;
@@ -56,15 +60,12 @@
 
 final class ModuleInfo {
 
-    // supplies the set of packages when ConcealedPackages not present
+    // supplies the set of packages when ModulePackages attribute not present
     private final Supplier<Set<String>> packageFinder;
 
-    // indicates if the Hashes attribute should be parsed
+    // indicates if the ModuleHashes attribute should be parsed
     private final boolean parseHashes;
 
-    // the builder, created when parsing
-    private ModuleDescriptor.Builder builder;
-
     private ModuleInfo(Supplier<Set<String>> pf, boolean ph) {
         packageFinder = pf;
         parseHashes = ph;
@@ -86,9 +87,8 @@
     {
         try {
             return new ModuleInfo(pf).doRead(new DataInputStream(in));
-        } catch (IllegalArgumentException iae) {
-            // IllegalArgumentException means a malformed class
-            throw invalidModuleDescriptor(iae.getMessage());
+        } catch (IllegalArgumentException | IllegalStateException e) {
+            throw invalidModuleDescriptor(e.getMessage());
         } catch (EOFException x) {
             throw truncatedModuleDescriptor();
         }
@@ -105,9 +105,8 @@
     {
         try {
             return new ModuleInfo(pf).doRead(new DataInputWrapper(bb));
-        } catch (IllegalArgumentException iae) {
-            // IllegalArgumentException means a malformed class
-            throw invalidModuleDescriptor(iae.getMessage());
+        } catch (IllegalArgumentException | IllegalStateException e) {
+            throw invalidModuleDescriptor(e.getMessage());
         } catch (EOFException x) {
             throw truncatedModuleDescriptor();
         } catch (IOException ioe) {
@@ -117,7 +116,7 @@
 
     /**
      * Reads a {@code module-info.class} from the given byte buffer
-     * but ignore the {@code Hashes} attribute.
+     * but ignore the {@code ModuleHashes} attribute.
      *
      * @throws InvalidModuleDescriptorException
      * @throws UncheckedIOException
@@ -127,8 +126,8 @@
     {
         try {
             return new ModuleInfo(pf, false).doRead(new DataInputWrapper(bb));
-        } catch (IllegalArgumentException iae) {
-            throw invalidModuleDescriptor(iae.getMessage());
+        } catch (IllegalArgumentException | IllegalStateException e) {
+            throw invalidModuleDescriptor(e.getMessage());
         } catch (EOFException x) {
             throw truncatedModuleDescriptor();
         } catch (IOException ioe) {
@@ -164,12 +163,8 @@
             throw invalidModuleDescriptor("access_flags should be ACC_MODULE");
 
         int this_class = in.readUnsignedShort();
-        String mn = cpool.getClassName(this_class);
-        int suffix = mn.indexOf("/module-info");
-        if (suffix < 1)
-            throw invalidModuleDescriptor("this_class not of form name/module-info");
-        mn = mn.substring(0, suffix).replace('/', '.');
-        builder = new ModuleDescriptor.Builder(mn);
+        if (this_class != 0)
+            throw invalidModuleDescriptor("this_class must be 0");
 
         int super_class = in.readUnsignedShort();
         if (super_class > 0)
@@ -192,6 +187,13 @@
         // the names of the attributes found in the class file
         Set<String> attributes = new HashSet<>();
 
+        Builder builder = null;
+        Set<String> packages = null;
+        String version = null;
+        String mainClass = null;
+        String[] osValues = null;
+        ModuleHashes hashes = null;
+
         for (int i = 0; i < attributes_count ; i++) {
             int name_index = in.readUnsignedShort();
             String attribute_name = cpool.getUtf8(name_index);
@@ -206,28 +208,28 @@
             switch (attribute_name) {
 
                 case MODULE :
-                    readModuleAttribute(mn, in, cpool);
+                    builder = readModuleAttribute(in, cpool);
                     break;
 
-                case CONCEALED_PACKAGES :
-                    readConcealedPackagesAttribute(in, cpool);
+                case MODULE_PACKAGES :
+                    packages = readModulePackagesAttribute(in, cpool);
                     break;
 
-                case VERSION :
-                    readVersionAttribute(in, cpool);
+                case MODULE_VERSION :
+                    version = readModuleVersionAttribute(in, cpool);
                     break;
 
-                case MAIN_CLASS :
-                    readMainClassAttribute(in, cpool);
+                case MODULE_MAIN_CLASS :
+                    mainClass = readModuleMainClassAttribute(in, cpool);
                     break;
 
-                case TARGET_PLATFORM :
-                    readTargetPlatformAttribute(in, cpool);
+                case MODULE_TARGET :
+                    osValues = readModuleTargetAttribute(in, cpool);
                     break;
 
-                case HASHES :
+                case MODULE_HASHES :
                     if (parseHashes) {
-                        readHashesAttribute(in, cpool);
+                        hashes = readModuleHashesAttribute(in, cpool);
                     } else {
                         in.skipBytes(length);
                     }
@@ -245,53 +247,91 @@
         }
 
         // the Module attribute is required
-        if (!attributes.contains(MODULE)) {
+        if (builder == null) {
             throw invalidModuleDescriptor(MODULE + " attribute not found");
         }
 
-        // If the ConcealedPackages attribute is not present then the
-        // packageFinder is used to to find any non-exported packages.
-        if (!attributes.contains(CONCEALED_PACKAGES) && packageFinder != null) {
-            Set<String> pkgs;
+        // If the ModulePackages attribute is not present then the packageFinder
+        // is used to find the set of packages
+        boolean usedPackageFinder = false;
+        if (packages == null && packageFinder != null) {
             try {
-                pkgs = new HashSet<>(packageFinder.get());
+                packages = new HashSet<>(packageFinder.get());
             } catch (UncheckedIOException x) {
                 throw x.getCause();
             }
-            pkgs.removeAll(builder.exportedPackages());
-            builder.conceals(pkgs);
+            usedPackageFinder = true;
+        }
+        if (packages != null) {
+            for (String pn : builder.exportedAndOpenPackages()) {
+                if (!packages.contains(pn)) {
+                    String tail;
+                    if (usedPackageFinder) {
+                        tail = " not found by package finder";
+                    } else {
+                        tail = " missing from ModulePackages attribute";
+                    }
+                    throw invalidModuleDescriptor("Package " + pn + tail);
+                }
+                packages.remove(pn);
+            }
+            builder.contains(packages);
         }
 
-        // Was the Synthetic attribute present?
-        if (attributes.contains(SYNTHETIC))
-            builder.synthetic(true);
+        if (version != null)
+            builder.version(version);
+        if (mainClass != null)
+            builder.mainClass(mainClass);
+        if (osValues != null) {
+            if (osValues[0] != null) builder.osName(osValues[0]);
+            if (osValues[1] != null) builder.osArch(osValues[1]);
+            if (osValues[2] != null) builder.osVersion(osValues[2]);
+        }
+        if (hashes != null)
+            builder.hashes(hashes);
 
         return builder.build();
     }
 
     /**
-     * Reads the Module attribute.
+     * Reads the Module attribute, returning the ModuleDescriptor.Builder to
+     * build the corresponding ModuleDescriptor.
      */
-    private void readModuleAttribute(String mn, DataInput in, ConstantPool cpool)
+    private Builder readModuleAttribute(DataInput in, ConstantPool cpool)
         throws IOException
     {
+        // module_name
+        int module_name_index = in.readUnsignedShort();
+        String mn = cpool.getUtf8AsBinaryName(module_name_index);
+
+        Builder builder = new ModuleDescriptor.Builder(mn, /*strict*/ false);
+
+        int module_flags = in.readUnsignedShort();
+        boolean open = ((module_flags & ACC_OPEN) != 0);
+        if (open)
+            builder.open(true);
+        if ((module_flags & ACC_SYNTHETIC) != 0)
+            builder.synthetic(true);
+
         int requires_count = in.readUnsignedShort();
         boolean requiresJavaBase = false;
         for (int i=0; i<requires_count; i++) {
             int index = in.readUnsignedShort();
             int flags = in.readUnsignedShort();
-            String dn = cpool.getUtf8(index);
-            Set<Modifier> mods;
+            String dn = cpool.getUtf8AsBinaryName(index);
+            Set<Requires.Modifier> mods;
             if (flags == 0) {
                 mods = Collections.emptySet();
             } else {
                 mods = new HashSet<>();
-                if ((flags & ACC_PUBLIC) != 0)
-                    mods.add(Modifier.PUBLIC);
+                if ((flags & ACC_TRANSITIVE) != 0)
+                    mods.add(Requires.Modifier.TRANSITIVE);
+                if ((flags & ACC_STATIC_PHASE) != 0)
+                    mods.add(Requires.Modifier.STATIC);
                 if ((flags & ACC_SYNTHETIC) != 0)
-                    mods.add(Modifier.SYNTHETIC);
+                    mods.add(Requires.Modifier.SYNTHETIC);
                 if ((flags & ACC_MANDATED) != 0)
-                    mods.add(Modifier.MANDATED);
+                    mods.add(Requires.Modifier.MANDATED);
             }
             builder.requires(mods, dn);
             if (dn.equals("java.base"))
@@ -311,17 +351,66 @@
         if (exports_count > 0) {
             for (int i=0; i<exports_count; i++) {
                 int index = in.readUnsignedShort();
-                String pkg = cpool.getUtf8(index).replace('/', '.');
+                String pkg = cpool.getUtf8AsBinaryName(index);
+
+                Set<Exports.Modifier> mods;
+                int flags = in.readUnsignedShort();
+                if (flags == 0) {
+                    mods = Collections.emptySet();
+                } else {
+                    mods = new HashSet<>();
+                    if ((flags & ACC_SYNTHETIC) != 0)
+                        mods.add(Exports.Modifier.SYNTHETIC);
+                    if ((flags & ACC_MANDATED) != 0)
+                        mods.add(Exports.Modifier.MANDATED);
+                }
+
                 int exports_to_count = in.readUnsignedShort();
                 if (exports_to_count > 0) {
                     Set<String> targets = new HashSet<>(exports_to_count);
                     for (int j=0; j<exports_to_count; j++) {
                         int exports_to_index = in.readUnsignedShort();
-                        targets.add(cpool.getUtf8(exports_to_index));
+                        targets.add(cpool.getUtf8AsBinaryName(exports_to_index));
                     }
-                    builder.exports(pkg, targets);
+                    builder.exports(mods, pkg, targets);
                 } else {
-                    builder.exports(pkg);
+                    builder.exports(mods, pkg);
+                }
+            }
+        }
+
+        int opens_count = in.readUnsignedShort();
+        if (opens_count > 0) {
+            if (open) {
+                throw invalidModuleDescriptor("The opens table for an open"
+                                              + " module must be 0 length");
+            }
+            for (int i=0; i<opens_count; i++) {
+                int index = in.readUnsignedShort();
+                String pkg = cpool.getUtf8AsBinaryName(index);
+
+                Set<Opens.Modifier> mods;
+                int flags = in.readUnsignedShort();
+                if (flags == 0) {
+                    mods = Collections.emptySet();
+                } else {
+                    mods = new HashSet<>();
+                    if ((flags & ACC_SYNTHETIC) != 0)
+                        mods.add(Opens.Modifier.SYNTHETIC);
+                    if ((flags & ACC_MANDATED) != 0)
+                        mods.add(Opens.Modifier.MANDATED);
+                }
+
+                int open_to_count = in.readUnsignedShort();
+                if (open_to_count > 0) {
+                    Set<String> targets = new HashSet<>(open_to_count);
+                    for (int j=0; j<open_to_count; j++) {
+                        int opens_to_index = in.readUnsignedShort();
+                        targets.add(cpool.getUtf8AsBinaryName(opens_to_index));
+                    }
+                    builder.opens(mods, pkg, targets);
+                } else {
+                    builder.opens(mods, pkg);
                 }
             }
         }
@@ -330,111 +419,114 @@
         if (uses_count > 0) {
             for (int i=0; i<uses_count; i++) {
                 int index = in.readUnsignedShort();
-                String sn = cpool.getClassName(index).replace('/', '.');
+                String sn = cpool.getClassNameAsBinaryName(index);
                 builder.uses(sn);
             }
         }
 
         int provides_count = in.readUnsignedShort();
         if (provides_count > 0) {
-            Map<String, Set<String>> pm = new HashMap<>();
             for (int i=0; i<provides_count; i++) {
                 int index = in.readUnsignedShort();
-                int with_index = in.readUnsignedShort();
-                String sn = cpool.getClassName(index).replace('/', '.');
-                String cn = cpool.getClassName(with_index).replace('/', '.');
-                // computeIfAbsent
-                Set<String> providers = pm.get(sn);
-                if (providers == null) {
-                    providers = new LinkedHashSet<>(); // preserve order
-                    pm.put(sn, providers);
+                String sn = cpool.getClassNameAsBinaryName(index);
+                int with_count = in.readUnsignedShort();
+                List<String> providers = new ArrayList<>(with_count);
+                for (int j=0; j<with_count; j++) {
+                    index = in.readUnsignedShort();
+                    String pn = cpool.getClassNameAsBinaryName(index);
+                    providers.add(pn);
                 }
-                providers.add(cn);
-            }
-            for (Map.Entry<String, Set<String>> e : pm.entrySet()) {
-                builder.provides(e.getKey(), e.getValue());
+                builder.provides(sn, providers);
             }
         }
+
+        return builder;
     }
 
     /**
-     * Reads the ConcealedPackages attribute
+     * Reads the ModulePackages attribute
      */
-    private void readConcealedPackagesAttribute(DataInput in, ConstantPool cpool)
+    private Set<String> readModulePackagesAttribute(DataInput in, ConstantPool cpool)
         throws IOException
     {
         int package_count = in.readUnsignedShort();
+        Set<String> packages = new HashSet<>(package_count);
         for (int i=0; i<package_count; i++) {
             int index = in.readUnsignedShort();
-            String pn = cpool.getUtf8(index).replace('/', '.');
-            builder.conceals(pn);
+            String pn = cpool.getUtf8AsBinaryName(index);
+            packages.add(pn);
         }
+        return packages;
     }
 
     /**
-     * Reads the Version attribute
+     * Reads the ModuleVersion attribute
      */
-    private void readVersionAttribute(DataInput in, ConstantPool cpool)
+    private String readModuleVersionAttribute(DataInput in, ConstantPool cpool)
         throws IOException
     {
         int index = in.readUnsignedShort();
-        builder.version(cpool.getUtf8(index));
+        return cpool.getUtf8(index);
     }
 
     /**
-     * Reads the MainClass attribute
+     * Reads the ModuleMainClass attribute
      */
-    private void readMainClassAttribute(DataInput in, ConstantPool cpool)
+    private String readModuleMainClassAttribute(DataInput in, ConstantPool cpool)
         throws IOException
     {
         int index = in.readUnsignedShort();
-        builder.mainClass(cpool.getClassName(index).replace('/', '.'));
+        return cpool.getClassNameAsBinaryName(index);
     }
 
     /**
-     * Reads the TargetPlatform attribute
+     * Reads the ModuleTarget attribute
      */
-    private void readTargetPlatformAttribute(DataInput in, ConstantPool cpool)
+    private String[] readModuleTargetAttribute(DataInput in, ConstantPool cpool)
         throws IOException
     {
+        String[] values = new String[3];
+
         int name_index = in.readUnsignedShort();
         if (name_index != 0)
-            builder.osName(cpool.getUtf8(name_index));
+            values[0] = cpool.getUtf8(name_index);
 
         int arch_index = in.readUnsignedShort();
         if (arch_index != 0)
-            builder.osArch(cpool.getUtf8(arch_index));
+            values[1] = cpool.getUtf8(arch_index);
 
         int version_index = in.readUnsignedShort();
         if (version_index != 0)
-            builder.osVersion(cpool.getUtf8(version_index));
+            values[2] = cpool.getUtf8(version_index);
+
+        return values;
     }
 
 
     /**
-     * Reads the Hashes attribute
-     *
-     * @apiNote For now the hash is stored in base64 as a UTF-8 string, this
-     * should be changed to be an array of u1.
+     * Reads the ModuleHashes attribute
      */
-    private void readHashesAttribute(DataInput in, ConstantPool cpool)
+    private ModuleHashes readModuleHashesAttribute(DataInput in, ConstantPool cpool)
         throws IOException
     {
-        int index = in.readUnsignedShort();
-        String algorithm = cpool.getUtf8(index);
+        int algorithm_index = in.readUnsignedShort();
+        String algorithm = cpool.getUtf8(algorithm_index);
 
         int hash_count = in.readUnsignedShort();
-
-        Map<String, String> map = new HashMap<>(hash_count);
+        Map<String, byte[]> map = new HashMap<>(hash_count);
         for (int i=0; i<hash_count; i++) {
-            index = in.readUnsignedShort();
-            String dn = cpool.getUtf8(index);
-            index = in.readUnsignedShort();
-            String hash = cpool.getUtf8(index);
-            map.put(dn, hash);
+            int module_name_index = in.readUnsignedShort();
+            String mn = cpool.getUtf8AsBinaryName(module_name_index);
+            int hash_length = in.readUnsignedShort();
+            if (hash_length == 0) {
+                throw invalidModuleDescriptor("hash_length == 0");
+            }
+            byte[] hash = new byte[hash_length];
+            in.readFully(hash);
+            map.put(mn, hash);
         }
 
-        builder.hashes(new ModuleHashes(algorithm, map));
+        return new ModuleHashes(algorithm, map);
     }
 
 
@@ -447,11 +539,11 @@
         if (name.equals(MODULE) ||
                 name.equals(SOURCE_FILE) ||
                 name.equals(SDE) ||
-                name.equals(CONCEALED_PACKAGES) ||
-                name.equals(VERSION) ||
-                name.equals(MAIN_CLASS) ||
-                name.equals(TARGET_PLATFORM) ||
-                name.equals(HASHES))
+                name.equals(MODULE_PACKAGES) ||
+                name.equals(MODULE_VERSION) ||
+                name.equals(MODULE_MAIN_CLASS) ||
+                name.equals(MODULE_TARGET) ||
+                name.equals(MODULE_HASHES))
             return true;
 
         return false;
@@ -461,8 +553,8 @@
      * Return true if the given attribute name is the name of a pre-defined
      * attribute that is not allowed in the class file.
      *
-     * Except for Module, InnerClasses, Synthetic, SourceFile, SourceDebugExtension,
-     * and Deprecated, none of the pre-defined attributes in JVMS 4.7 may appear.
+     * Except for Module, InnerClasses, SourceFile, SourceDebugExtension, and
+     * Deprecated, none of the pre-defined attributes in JVMS 4.7 may appear.
      */
     private static boolean isAttributeDisallowed(String name) {
         Set<String> notAllowed = predefinedNotAllowed;
@@ -477,12 +569,11 @@
                     "LineNumberTable",
                     "LocalVariableTable",
                     "LocalVariableTypeTable",
-                    "RuntimeVisibleAnnotations",
-                    "RuntimeInvisibleAnnotations",
                     "RuntimeVisibleParameterAnnotations",
                     "RuntimeInvisibleParameterAnnotations",
                     "RuntimeVisibleTypeAnnotations",
                     "RuntimeInvisibleTypeAnnotations",
+                    "Synthetic",
                     "AnnotationDefault",
                     "BootstrapMethods",
                     "MethodParameters");
@@ -495,7 +586,6 @@
     private static volatile Set<String> predefinedNotAllowed;
 
 
-
     /**
      * The constant pool in a class file.
      */
@@ -628,6 +718,11 @@
             return getUtf8(((IndexEntry) e).index);
         }
 
+        String getClassNameAsBinaryName(int index) {
+            String value = getClassName(index);
+            return value.replace('/', '.');  // internal form -> binary name
+        }
+
         String getUtf8(int index) {
             checkIndex(index);
             Entry e = pool[index];
@@ -638,6 +733,11 @@
             return (String) (((ValueEntry) e).value);
         }
 
+        String getUtf8AsBinaryName(int index) {
+            String value = getUtf8(index);
+            return value.replace('/', '.');  // internal -> binary name
+        }
+
         void checkIndex(int index) {
             if (index < 1 || index >= pool.length)
                 throw invalidModuleDescriptor("Index into constant pool out of range");
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java
index fa40f3b..15df030 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java
@@ -40,9 +40,10 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -54,7 +55,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import jdk.internal.jmod.JmodFile;
@@ -399,8 +399,8 @@
      *
      * 1. The module name (and optionally the version) is derived from the file
      *    name of the JAR file
-     * 2. The packages of all .class files in the JAR file are exported
-     * 3. It has no module-private/concealed packages
+     * 2. All packages are exported and open
+     * 3. It has no non-exported/non-open packages
      * 4. The contents of any META-INF/services configuration files are mapped
      *    to "provides" declarations
      * 5. The Main-Class attribute in the main attributes of the JAR manifest
@@ -440,8 +440,7 @@
 
         // Builder throws IAE if module name is empty or invalid
         ModuleDescriptor.Builder builder
-            = new ModuleDescriptor.Builder(mn)
-                .automatic()
+            = ModuleDescriptor.automaticModule(mn)
                 .requires(Set.of(Requires.Modifier.MANDATED), "java.base");
         if (vs != null)
             builder.version(vs);
@@ -455,13 +454,12 @@
 
         Set<String> resources = map.get(Boolean.FALSE);
         Set<String> configFiles = map.get(Boolean.TRUE);
-
-        // all packages are exported
+        // all packages are exported and open
         resources.stream()
                 .map(this::toPackageName)
                 .flatMap(Optional::stream)
                 .distinct()
-                .forEach(builder::exports);
+                .forEach(pn -> builder.exports(pn).opens(pn));
 
         // map names of service configuration files to service names
         Set<String> serviceNames = configFiles.stream()
@@ -472,7 +470,7 @@
         // parse each service configuration file
         for (String sn : serviceNames) {
             JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
-            Set<String> providerClasses = new LinkedHashSet<>();
+            List<String> providerClasses = new ArrayList<>();
             try (InputStream in = jf.getInputStream(entry)) {
                 BufferedReader reader
                     = new BufferedReader(new InputStreamReader(in, "UTF-8"));
@@ -493,7 +491,7 @@
             Attributes attrs = man.getMainAttributes();
             String mainClass = attrs.getValue(Attributes.Name.MAIN_CLASS);
             if (mainClass != null)
-                builder.mainClass(mainClass);
+                builder.mainClass(mainClass.replace("/", "."));
         }
 
         return builder.build();
@@ -504,6 +502,7 @@
      */
     private static class Patterns {
         static final Pattern DASH_VERSION = Pattern.compile("-(\\d+(\\.|$))");
+        static final Pattern TRAILING_VERSION = Pattern.compile("(\\.|\\d)*$");
         static final Pattern NON_ALPHANUM = Pattern.compile("[^A-Za-z0-9]");
         static final Pattern REPEATING_DOTS = Pattern.compile("(\\.)(\\1)+");
         static final Pattern LEADING_DOTS = Pattern.compile("^\\.");
@@ -514,6 +513,9 @@
      * Clean up candidate module name derived from a JAR file name.
      */
     private static String cleanModuleName(String mn) {
+        // drop trailing version from name
+        mn = Patterns.TRAILING_VERSION.matcher(mn).replaceAll("");
+
         // replace non-alphanumeric
         mn = Patterns.NON_ALPHANUM.matcher(mn).replaceAll(".");
 
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
index 34d1363..cbf84cf 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java
@@ -60,8 +60,8 @@
     // the function that computes the hash of this module reference
     private final HashSupplier hasher;
 
-    // cached hash string to avoid needing to compute it many times
-    private String cachedHash;
+    // cached hash to avoid needing to compute it many times
+    private byte[] cachedHash;
 
 
     /**
@@ -183,13 +183,13 @@
     }
 
     /**
-     * Computes the hash of this module, returning it as a hex string.
-     * Returns {@code null} if the hash cannot be computed.
+     * Computes the hash of this module. Returns {@code null} if the hash
+     * cannot be computed.
      *
      * @throws java.io.UncheckedIOException if an I/O error occurs
      */
-    String computeHash(String algorithm) {
-        String result = cachedHash;
+    byte[] computeHash(String algorithm) {
+        byte[] result = cachedHash;
         if (result != null)
             return result;
         if (hasher == null)
@@ -211,8 +211,11 @@
     public int hashCode() {
         int hc = hash;
         if (hc == 0) {
-            hc = Objects.hash(descriptor, location, readerSupplier, hasher,
-                    Boolean.valueOf(patched));
+            hc = descriptor.hashCode();
+            hc = 43 * hc + readerSupplier.hashCode();
+            hc = 43 * hc + Objects.hashCode(location);
+            hc = 43 * hc + Objects.hashCode(hasher);
+            hc = 43 * hc + Boolean.hashCode(patched);
             if (hc == 0)
                 hc = -1;
             hash = hc;
diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java
index 8393bd0..e53ba04 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java
@@ -51,6 +51,7 @@
 import jdk.internal.jmod.JmodFile;
 import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ModuleBootstrap;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleHashes.HashSupplier;
 import jdk.internal.module.ModulePatcher;
@@ -80,9 +81,8 @@
                                              HashSupplier hasher) {
 
         ModuleReference mref = new ModuleReference(md, uri, supplier, hasher);
-
         if (JLA.getBootLayer() == null)
-            mref = ModulePatcher.interposeIfNeeded(mref);
+            mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
 
         return mref;
     }
@@ -93,7 +93,7 @@
     static ModuleReference newJarModule(ModuleDescriptor md, Path file) {
         URI uri = file.toUri();
         Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
-        HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a);
+        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
         return newModule(md, uri, supplier, hasher);
     }
 
@@ -103,7 +103,7 @@
     static ModuleReference newJModModule(ModuleDescriptor md, Path file) {
         URI uri = file.toUri();
         Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
-        HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a);
+        HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
         return newModule(md, file.toUri(), supplier, hasher);
     }
 
diff --git a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
index adc60da..5f716b1 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java
@@ -26,9 +26,12 @@
 package java.lang.module;
 
 import java.io.PrintStream;
+import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.reflect.Layer;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Deque;
 import java.util.HashMap;
@@ -47,12 +50,15 @@
 /**
  * The resolver used by {@link Configuration#resolveRequires} and
  * {@link Configuration#resolveRequiresAndUses}.
+ *
+ * @implNote The resolver is used at VM startup and so deliberately avoids
+ * using lambda and stream usages in code paths used during startup.
  */
 
 final class Resolver {
 
     private final ModuleFinder beforeFinder;
-    private final Configuration parent;
+    private final List<Configuration> parents;
     private final ModuleFinder afterFinder;
     private final PrintStream traceOutput;
 
@@ -61,11 +67,11 @@
 
 
     Resolver(ModuleFinder beforeFinder,
-             Configuration parent,
+             List<Configuration> parents,
              ModuleFinder afterFinder,
              PrintStream traceOutput) {
         this.beforeFinder = beforeFinder;
-        this.parent = parent;
+        this.parents = parents;
         this.afterFinder = afterFinder;
         this.traceOutput = traceOutput;
     }
@@ -85,10 +91,12 @@
             // find root module
             ModuleReference mref = findWithBeforeFinder(root);
             if (mref == null) {
-                if (parent.findModule(root).isPresent()) {
+
+                if (findInParent(root) != null) {
                     // in parent, nothing to do
                     continue;
                 }
+
                 mref = findWithAfterFinder(root);
                 if (mref == null) {
                     fail("Module %s not found", root);
@@ -125,13 +133,21 @@
 
             // process dependences
             for (ModuleDescriptor.Requires requires : descriptor.requires()) {
+
+                // only required at compile-time
+                if (requires.modifiers().contains(Modifier.STATIC))
+                    continue;
+
                 String dn = requires.name();
 
                 // find dependence
                 ModuleReference mref = findWithBeforeFinder(dn);
                 if (mref == null) {
-                    if (parent.findModule(dn).isPresent())
+
+                    if (findInParent(dn) != null) {
+                        // dependence is in parent
                         continue;
+                    }
 
                     mref = findWithAfterFinder(dn);
                     if (mref == null) {
@@ -174,7 +190,9 @@
             ModuleDescriptor descriptor = mref.descriptor();
             if (!descriptor.provides().isEmpty()) {
 
-                for (String sn : descriptor.provides().keySet()) {
+                for (Provides provides :  descriptor.provides()) {
+                    String sn = provides.service();
+
                     // computeIfAbsent
                     Set<ModuleReference> providers = availableProviders.get(sn);
                     if (providers == null) {
@@ -191,19 +209,23 @@
         Deque<ModuleDescriptor> q = new ArrayDeque<>();
 
         // the initial set of modules that may use services
-        Set<ModuleDescriptor> candidateConsumers = new HashSet<>();
-        Configuration p = parent;
-        while (p != null) {
-            candidateConsumers.addAll(p.descriptors());
-            p = p.parent().orElse(null);
+        Set<ModuleDescriptor> initialConsumers;
+        if (Layer.boot() == null) {
+            initialConsumers = new HashSet<>();
+        } else {
+            initialConsumers = parents.stream()
+                    .flatMap(Configuration::configurations)
+                    .distinct()
+                    .flatMap(c -> c.descriptors().stream())
+                    .collect(Collectors.toSet());
         }
         for (ModuleReference mref : nameToReference.values()) {
-            candidateConsumers.add(mref.descriptor());
+            initialConsumers.add(mref.descriptor());
         }
 
-
         // Where there is a consumer of a service then resolve all modules
         // that provide an implementation of that service
+        Set<ModuleDescriptor> candidateConsumers = initialConsumers;
         do {
             for (ModuleDescriptor descriptor : candidateConsumers) {
                 if (!descriptor.uses().isEmpty()) {
@@ -234,7 +256,6 @@
             }
 
             candidateConsumers = resolve(q);
-
         } while (!candidateConsumers.isEmpty());
 
         return this;
@@ -429,21 +450,21 @@
             for (String dn : hashes.names()) {
                 ModuleReference other = nameToReference.get(dn);
                 if (other == null) {
-                    other = parent.findModule(dn)
-                            .map(ResolvedModule::reference)
-                            .orElse(null);
+                    ResolvedModule resolvedModule = findInParent(dn);
+                    if (resolvedModule != null)
+                        other = resolvedModule.reference();
                 }
 
                 // skip checking the hash if the module has been patched
                 if (other != null && !other.isPatched()) {
-                    String recordedHash = hashes.hashFor(dn);
-                    String actualHash = other.computeHash(algorithm);
+                    byte[] recordedHash = hashes.hashFor(dn);
+                    byte[] actualHash = other.computeHash(algorithm);
                     if (actualHash == null)
                         fail("Unable to compute the hash of module %s", dn);
-                    if (!recordedHash.equals(actualHash)) {
+                    if (!Arrays.equals(recordedHash, actualHash)) {
                         fail("Hash of %s (%s) differs to expected hash (%s)" +
-                             " recorded in %s", dn, actualHash, recordedHash,
-                             descriptor.name());
+                             " recorded in %s", dn, toHexString(actualHash),
+                             toHexString(recordedHash), descriptor.name());
                     }
                 }
             }
@@ -451,52 +472,68 @@
         }
     }
 
+    private static String toHexString(byte[] ba) {
+        StringBuilder sb = new StringBuilder(ba.length * 2);
+        for (byte b: ba) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
 
     /**
      * Computes the readability graph for the modules in the given Configuration.
      *
      * The readability graph is created by propagating "requires" through the
-     * "public requires" edges of the module dependence graph. So if the module
-     * dependence graph has m1 requires m2 && m2 requires public m3 then the
-     * resulting readability graph will contain m1 reads m2, m1 reads m3, and
-     * m2 reads m3.
+     * "requires transitive" edges of the module dependence graph. So if the
+     * module dependence graph has m1 requires m2 && m2 requires transitive m3
+     * then the resulting readability graph will contain m1 reads m2, m1 reads m3,
+     * and m2 reads m3.
      */
     private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {
 
+        // initial capacity of maps to avoid resizing
+        int capacity = 1 + (4 * nameToReference.size())/ 3;
+
         // the "reads" graph starts as a module dependence graph and
         // is iteratively updated to be the readability graph
-        Map<ResolvedModule, Set<ResolvedModule>> g1 = new HashMap<>();
+        Map<ResolvedModule, Set<ResolvedModule>> g1 = new HashMap<>(capacity);
 
-        // the "requires public" graph, contains requires public edges only
-        Map<ResolvedModule, Set<ResolvedModule>> g2 = new HashMap<>();
+        // the "requires transitive" graph, contains requires transitive edges only
+        Map<ResolvedModule, Set<ResolvedModule>> g2;
 
-
-        // need "requires public" from the modules in parent configurations as
-        // there may be selected modules that have a dependency on modules in
+        // need "requires transitive" from the modules in parent configurations
+        // as there may be selected modules that have a dependency on modules in
         // the parent configuration.
-
-        Configuration p = parent;
-        while (p != null) {
-            for (ModuleDescriptor descriptor : p.descriptors()) {
-                String name = descriptor.name();
-                ResolvedModule m1 = p.findModule(name)
-                    .orElseThrow(() -> new InternalError(name + " not found"));
-                for (ModuleDescriptor.Requires requires : descriptor.requires()) {
-                    if (requires.modifiers().contains(Modifier.PUBLIC)) {
-                        String dn = requires.name();
-                        ResolvedModule m2 = p.findModule(dn)
-                            .orElseThrow(() -> new InternalError(dn + " not found"));
-                        g2.computeIfAbsent(m1, k -> new HashSet<>()).add(m2);
-                    }
-                }
-            }
-
-            p = p.parent().orElse(null);
+        if (Layer.boot() == null) {
+            g2 = new HashMap<>(capacity);
+        } else {
+            g2 = parents.stream()
+                .flatMap(Configuration::configurations)
+                .distinct()
+                .flatMap(c ->
+                    c.modules().stream().flatMap(m1 ->
+                        m1.descriptor().requires().stream()
+                            .filter(r -> r.modifiers().contains(Modifier.TRANSITIVE))
+                            .flatMap(r -> {
+                                Optional<ResolvedModule> m2 = c.findModule(r.name());
+                                assert m2.isPresent()
+                                        || r.modifiers().contains(Modifier.STATIC);
+                                return m2.stream();
+                            })
+                            .map(m2 -> Map.entry(m1, m2))
+                    )
+                )
+                // stream of m1->m2
+                .collect(Collectors.groupingBy(Map.Entry::getKey,
+                        HashMap::new,
+                        Collectors.mapping(Map.Entry::getValue, Collectors.toSet())
+            ));
         }
 
         // populate g1 and g2 with the dependences from the selected modules
 
-        Map<String, ResolvedModule> nameToResolved = new HashMap<>();
+        Map<String, ResolvedModule> nameToResolved = new HashMap<>(capacity);
 
         for (ModuleReference mref : nameToReference.values()) {
             ModuleDescriptor descriptor = mref.descriptor();
@@ -505,20 +542,21 @@
             ResolvedModule m1 = computeIfAbsent(nameToResolved, name, cf, mref);
 
             Set<ResolvedModule> reads = new HashSet<>();
-            Set<ResolvedModule> requiresPublic = new HashSet<>();
+            Set<ResolvedModule> requiresTransitive = new HashSet<>();
 
             for (ModuleDescriptor.Requires requires : descriptor.requires()) {
                 String dn = requires.name();
 
-                ResolvedModule m2;
+                ResolvedModule m2 = null;
                 ModuleReference mref2 = nameToReference.get(dn);
                 if (mref2 != null) {
                     // same configuration
                     m2 = computeIfAbsent(nameToResolved, dn, cf, mref2);
                 } else {
                     // parent configuration
-                    m2 = parent.findModule(dn).orElse(null);
+                    m2 = findInParent(dn);
                     if (m2 == null) {
+                        assert requires.modifiers().contains(Modifier.STATIC);
                         continue;
                     }
                 }
@@ -526,9 +564,9 @@
                 // m1 requires m2 => m1 reads m2
                 reads.add(m2);
 
-                // m1 requires public m2
-                if (requires.modifiers().contains(Modifier.PUBLIC)) {
-                    requiresPublic.add(m2);
+                // m1 requires transitive m2
+                if (requires.modifiers().contains(Modifier.TRANSITIVE)) {
+                    requiresTransitive.add(m2);
                 }
 
             }
@@ -538,7 +576,7 @@
             if (descriptor.isAutomatic()) {
 
                 // reads all selected modules
-                // `requires public` all selected automatic modules
+                // `requires transitive` all selected automatic modules
                 for (ModuleReference mref2 : nameToReference.values()) {
                     ModuleDescriptor descriptor2 = mref2.descriptor();
                     String name2 = descriptor2.name();
@@ -548,40 +586,42 @@
                             = computeIfAbsent(nameToResolved, name2, cf, mref2);
                         reads.add(m2);
                         if (descriptor2.isAutomatic())
-                            requiresPublic.add(m2);
+                            requiresTransitive.add(m2);
                     }
                 }
 
                 // reads all modules in parent configurations
-                // `requires public` all automatic modules in parent configurations
-                p = parent;
-                while (p != null) {
-                    for (ResolvedModule m : p.modules()) {
-                        reads.add(m);
-                        if (m.reference().descriptor().isAutomatic())
-                            requiresPublic.add(m);
-                    }
-                    p = p.parent().orElse(null);
+                // `requires transitive` all automatic modules in parent
+                // configurations
+                for (Configuration parent : parents) {
+                    parent.configurations()
+                            .map(Configuration::modules)
+                            .flatMap(Set::stream)
+                            .forEach(m -> {
+                                reads.add(m);
+                                if (m.reference().descriptor().isAutomatic())
+                                    requiresTransitive.add(m);
+                            });
                 }
-
             }
 
             g1.put(m1, reads);
-            g2.put(m1, requiresPublic);
+            g2.put(m1, requiresTransitive);
         }
 
-        // Iteratively update g1 until there are no more requires public to propagate
+        // Iteratively update g1 until there are no more requires transitive
+        // to propagate
         boolean changed;
-        Set<ResolvedModule> toAdd = new HashSet<>();
+        List<ResolvedModule> toAdd = new ArrayList<>();
         do {
             changed = false;
             for (Set<ResolvedModule> m1Reads : g1.values()) {
                 for (ResolvedModule m2 : m1Reads) {
-                    Set<ResolvedModule> m2RequiresPublic = g2.get(m2);
-                    if (m2RequiresPublic != null) {
-                        for (ResolvedModule m3 : m2RequiresPublic) {
+                    Set<ResolvedModule> m2RequiresTransitive = g2.get(m2);
+                    if (m2RequiresTransitive != null) {
+                        for (ResolvedModule m3 : m2RequiresTransitive) {
                             if (!m1Reads.contains(m3)) {
-                                // m1 reads m2, m2 requires public m3
+                                // m1 reads m2, m2 requires transitive m3
                                 // => need to add m1 reads m3
                                 toAdd.add(m3);
                             }
@@ -655,7 +695,7 @@
                     // source is exported to descriptor2
                     String source = export.source();
                     ModuleDescriptor other
-                        = packageToExporter.put(source, descriptor2);
+                        = packageToExporter.putIfAbsent(source, descriptor2);
 
                     if (other != null && other != descriptor2) {
                         // package might be local to descriptor1
@@ -692,12 +732,8 @@
                 }
 
                 // provides S
-                for (Map.Entry<String, ModuleDescriptor.Provides> entry :
-                        descriptor1.provides().entrySet()) {
-                    String service = entry.getKey();
-                    ModuleDescriptor.Provides provides = entry.getValue();
-
-                    String pn = packageName(service);
+                for (ModuleDescriptor.Provides provides : descriptor1.provides()) {
+                    String pn = packageName(provides.service());
                     if (!packageToExporter.containsKey(pn)) {
                         fail("Module %s does not read a module that exports %s",
                              descriptor1.name(), pn);
@@ -717,6 +753,18 @@
 
     }
 
+    /**
+     * Find a module of the given name in the parent configurations
+     */
+    private ResolvedModule findInParent(String mn) {
+        for (Configuration parent : parents) {
+            Optional<ResolvedModule> om = parent.findModule(mn);
+            if (om.isPresent())
+                return om.get();
+        }
+        return null;
+    }
+
 
     /**
      * Invokes the beforeFinder to find method to find the given module.
@@ -755,15 +803,18 @@
             if (afterModules.isEmpty())
                 return beforeModules;
 
-            if (beforeModules.isEmpty() && parent == Configuration.empty())
+            if (beforeModules.isEmpty()
+                    && parents.size() == 1
+                    && parents.get(0) == Configuration.empty())
                 return afterModules;
 
             Set<ModuleReference> result = new HashSet<>(beforeModules);
             for (ModuleReference mref : afterModules) {
                 String name = mref.descriptor().name();
                 if (!beforeFinder.find(name).isPresent()
-                        && !parent.findModule(name).isPresent())
+                        && findInParent(name) == null) {
                     result.add(mref);
+                }
             }
 
             return result;
diff --git a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
index 9fae75c..6de8ce8 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
+++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
@@ -39,6 +39,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
@@ -53,6 +54,7 @@
 import jdk.internal.jimage.ImageReaderFactory;
 import jdk.internal.misc.JavaNetUriAccess;
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.ModuleBootstrap;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleHashes.HashSupplier;
 import jdk.internal.module.SystemModules;
@@ -64,7 +66,7 @@
  * run-time image.
  *
  * The modules linked into the run-time image are assumed to have the
- * ConcealedPackages attribute.
+ * Packages attribute.
  */
 
 class SystemModuleFinder implements ModuleFinder {
@@ -102,8 +104,11 @@
         int n = names.length;
         moduleCount.add(n);
 
-        Set<ModuleReference> mods = new HashSet<>(n);
-        Map<String, ModuleReference> map = new HashMap<>(n);
+        ModuleReference[] mods = new ModuleReference[n];
+
+        @SuppressWarnings(value = {"rawtypes", "unchecked"})
+        Entry<String, ModuleReference>[] map
+            = (Entry<String, ModuleReference>[])new Entry[n];
 
         for (int i = 0; i < n; i++) {
             ModuleDescriptor md = descriptors[i];
@@ -111,16 +116,16 @@
             // create the ModuleReference
             ModuleReference mref = toModuleReference(md, hashSupplier(i, names[i]));
 
-            mods.add(mref);
-            map.put(names[i], mref);
+            mods[i] = mref;
+            map[i] = Map.entry(names[i], mref);
 
             // counters
             packageCount.add(md.packages().size());
             exportsCount.add(md.exports().size());
         }
 
-        modules = Collections.unmodifiableSet(mods);
-        nameToModule = map;
+        modules = Set.of(mods);
+        nameToModule = Map.ofEntries(map);
 
         initTime.addElapsedTimeFrom(t0);
     }
@@ -190,7 +195,7 @@
             new ModuleReference(md, uri, readerSupplier, hash);
 
         // may need a reference to a patched module if --patch-module specified
-        mref = ModulePatcher.interposeIfNeeded(mref);
+        mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
 
         return mref;
     }
@@ -199,7 +204,7 @@
         if (isFastPathSupported()) {
             return new HashSupplier() {
                 @Override
-                public String generate(String algorithm) {
+                public byte[] generate(String algorithm) {
                     return SystemModules.MODULES_TO_HASH[index];
                 }
             };
@@ -213,7 +218,7 @@
      * It will get the recorded hashes from module-info.class.
      */
     private static class Hashes {
-        static Map<String, String> hashes = new HashMap<>();
+        static Map<String, byte[]> hashes = new HashMap<>();
 
         static void add(ModuleDescriptor descriptor) {
             Optional<ModuleHashes> ohashes = descriptor.hashes();
@@ -228,7 +233,7 @@
 
             return new HashSupplier() {
                 @Override
-                public String generate(String algorithm) {
+                public byte[] generate(String algorithm) {
                     return hashes.get(name);
                 }
             };
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
index 353870b..a046a74 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
@@ -25,12 +25,12 @@
 
 package java.lang.reflect;
 
+import java.lang.annotation.Annotation;
 import java.security.AccessController;
 
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 import jdk.internal.reflect.ReflectionFactory;
-import java.lang.annotation.Annotation;
 
 /**
  * The AccessibleObject class is the base class for Field, Method and
@@ -81,8 +81,10 @@
      * <p>This method cannot be used to enable access to an object that is a
      * {@link Member member} of a class in a different module to the caller and
      * where the class is in a package that is not exported to the caller's
-     * module. Additionally, this method cannot be used to enable access to
-     * non-public members of {@code AccessibleObject} or {@link Module}.
+     * module. Additionally, if the member is non-public or its declaring
+     * class is non-public, then this method can only be used to enable access
+     * if the package is {@link Module#isOpen(String,Module) open} to at least
+     * the caller's module.
      *
      * <p>If there is a security manager, its
      * {@code checkPermission} method is first called with a
@@ -126,8 +128,10 @@
      * <p>This method cannot be used to enable access to an object that is a
      * {@link Member member} of a class in a different module to the caller and
      * where the class is in a package that is not exported to the caller's
-     * module. Additionally, this method cannot be used to enable access to
-     * non-public members of {@code AccessibleObject} or {@link Module}.
+     * module. Additionally, if the member is non-public or its declaring
+     * class is non-public, then this method can only be used to enable access
+     * if the package is {@link Module#isOpen(String,Module) open} to at least
+     * the caller's module.
      *
      * <p>If there is a security manager, its
      * {@code checkPermission} method is first called with a
@@ -138,6 +142,7 @@
      * @throws SecurityException if the request is denied
      * @see SecurityManager#checkPermission
      * @see ReflectPermission
+     * @see java.lang.invoke.MethodHandles#privateLookupIn
      */
     public void setAccessible(boolean flag) {
         AccessibleObject.checkPermission();
@@ -161,35 +166,39 @@
         Module callerModule = caller.getModule();
         Module declaringModule = declaringClass.getModule();
 
-        if (callerModule != declaringModule
-                && callerModule != Object.class.getModule()) {
+        if (callerModule == declaringModule) return;
+        if (callerModule == Object.class.getModule()) return;
+        if (!declaringModule.isNamed()) return;
 
-            // check exports to target module
-            String pn = packageName(declaringClass);
-            if (!declaringModule.isExported(pn, callerModule)) {
-                String msg = "Unable to make member of "
-                        + declaringClass + " accessible:  "
-                        + declaringModule + " does not export "
-                        + pn + " to " + callerModule;
-                Reflection.throwInaccessibleObjectException(msg);
-            }
+        // package is open to caller
+        String pn = packageName(declaringClass);
+        if (declaringModule.isOpen(pn, callerModule))
+            return;
 
+        // package is exported to caller and class/member is public
+        boolean isExported = declaringModule.isExported(pn, callerModule);
+        boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
+        int modifiers;
+        if (this instanceof Executable) {
+            modifiers = ((Executable) this).getModifiers();
+        } else {
+            modifiers = ((Field) this).getModifiers();
         }
+        boolean isMemberPublic = Modifier.isPublic(modifiers);
+        if (isExported && isClassPublic && isMemberPublic)
+            return;
 
-        if (declaringClass == Module.class
-                || declaringClass == AccessibleObject.class) {
-            int modifiers;
-            if (this instanceof Executable) {
-                modifiers = ((Executable) this).getModifiers();
-            } else {
-                modifiers = ((Field) this).getModifiers();
-            }
-            if (!Modifier.isPublic(modifiers)) {
-                String msg = "Cannot make a non-public member of "
-                        + declaringClass + " accessible";
-                Reflection.throwInaccessibleObjectException(msg);
-            }
-        }
+        // not accessible
+        String msg = "Unable to make ";
+        if (this instanceof Field)
+            msg += "field ";
+        msg += this + " accessible: " + declaringModule + " does not \"";
+        if (isClassPublic && isMemberPublic)
+            msg += "exports";
+        else
+            msg += "opens";
+        msg += " " + pn + "\" to " + callerModule;
+        Reflection.throwInaccessibleObjectException(msg);
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
index 6e220a5..7466c57 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
@@ -27,23 +27,29 @@
 
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ResolvedModule;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import jdk.internal.loader.ClassLoaderValue;
 import jdk.internal.loader.Loader;
 import jdk.internal.loader.LoaderPool;
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.Modules;
 import jdk.internal.module.ServicesCatalog;
-import jdk.internal.module.ServicesCatalog.ServiceProvider;
 import sun.security.util.SecurityConstants;
 
 
@@ -55,7 +61,7 @@
  * Creating a layer informs the Java virtual machine about the classes that
  * may be loaded from modules so that the Java virtual machine knows which
  * module that each class is a member of. Each layer, except the {@link
- * #empty() empty} layer, has a {@link #parent() parent}. </p>
+ * #empty() empty} layer, has at least one {@link #parents() parent}. </p>
  *
  * <p> Creating a layer creates a {@link Module} object for each {@link
  * ResolvedModule} in the configuration. For each resolved module that is
@@ -71,7 +77,11 @@
  * mapped to a single class loader or where each module is mapped to its own
  * class loader. The {@link #defineModules defineModules} method is for more
  * advanced cases where modules are mapped to custom class loaders by means of
- * a function specified to the method. </p>
+ * a function specified to the method. Each of these methods has an instance
+ * and static variant. The instance methods create a layer with the receiver
+ * as the parent layer. The static methods are for more advanced cases where
+ * there can be more than one parent layer or a {@link Layer.Controller
+ * Controller} is needed to control modules in the layer. </p>
  *
  * <p> A Java virtual machine has at least one non-empty layer, the {@link
  * #boot() boot} layer, that is created when the Java virtual machine is
@@ -80,7 +90,7 @@
  * The modules in the boot layer are mapped to the bootstrap class loader and
  * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
  * built-in</a> into the Java virtual machine. The boot layer will often be
- * the {@link #parent() parent} when creating additional layers. </p>
+ * the {@link #parents() parent} when creating additional layers. </p>
  *
  * <p> As when creating a {@code Configuration},
  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive
@@ -123,30 +133,29 @@
 
     // the empty Layer
     private static final Layer EMPTY_LAYER
-        = new Layer(Configuration.empty(), null, null);
+        = new Layer(Configuration.empty(), List.of(), null);
 
     // the configuration from which this Layer was created
     private final Configuration cf;
 
-    // parent layer, null in the case of the empty layer
-    private final Layer parent;
+    // parent layers, empty in the case of the empty layer
+    private final List<Layer> parents;
 
     // maps module name to jlr.Module
     private final Map<String, Module> nameToModule;
 
-
     /**
      * Creates a new Layer from the modules in the given configuration.
      */
     private Layer(Configuration cf,
-                  Layer parent,
+                  List<Layer> parents,
                   Function<String, ClassLoader> clf)
     {
         this.cf = cf;
-        this.parent = parent;
+        this.parents = parents; // no need to do defensive copy
 
         Map<String, Module> map;
-        if (parent == null) {
+        if (parents.isEmpty()) {
             map = Collections.emptyMap();
         } else {
             map = Module.defineModules(cf, clf, this);
@@ -154,12 +163,230 @@
         this.nameToModule = map; // no need to do defensive copy
     }
 
+    /**
+     * Controls a layer. The static methods defined by {@link Layer} to create
+     * module layers return a {@code Controller} that can be used to control
+     * modules in the layer.
+     *
+     * @apiNote Care should be taken with {@code Controller} objects, they
+     * should never be shared with untrusted code.
+     *
+     * @since 9
+     */
+    public static final class Controller {
+        private final Layer layer;
+
+        Controller(Layer layer) {
+            this.layer = layer;
+        }
+
+        /**
+         * Returns the layer that this object controls.
+         *
+         * @return the layer
+         */
+        public Layer layer() {
+            return layer;
+        }
+
+        private void ensureInLayer(Module source) {
+            if (!layer.modules().contains(source))
+                throw new IllegalArgumentException(source + " not in layer");
+        }
+
+
+        /**
+         * Updates module {@code source} in the layer to read module
+         * {@code target}. This method is a no-op if {@code source} already
+         * reads {@code target}.
+         *
+         * @implNote <em>Read edges</em> added by this method are <em>weak</em>
+         * and do not prevent {@code target} from being GC'ed when {@code source}
+         * is strongly reachable.
+         *
+         * @param  source
+         *         The source module
+         * @param  target
+         *         The target module to read
+         *
+         * @return This controller
+         *
+         * @throws IllegalArgumentException
+         *         If {@code source} is not in the layer
+         *
+         * @see Module#addReads
+         */
+        public Controller addReads(Module source, Module target) {
+            Objects.requireNonNull(source);
+            Objects.requireNonNull(target);
+            ensureInLayer(source);
+            Modules.addReads(source, target);
+            return this;
+        }
+
+        /**
+         * Updates module {@code source} in the layer to open a package to
+         * module {@code target}. This method is a no-op if {@code source}
+         * already opens the package to at least {@code target}.
+         *
+         * @param  source
+         *         The source module
+         * @param  pn
+         *         The package name
+         * @param  target
+         *         The target module to read
+         *
+         * @return This controller
+         *
+         * @throws IllegalArgumentException
+         *         If {@code source} is not in the layer or the package is not
+         *         in the source module
+         *
+         * @see Module#addOpens
+         */
+        public Controller addOpens(Module source, String pn, Module target) {
+            Objects.requireNonNull(source);
+            Objects.requireNonNull(source);
+            Objects.requireNonNull(target);
+            ensureInLayer(source);
+            Modules.addOpens(source, pn, target);
+            return this;
+        }
+    }
+
 
     /**
      * Creates a new layer, with this layer as its parent, by defining the
      * modules in the given {@code Configuration} to the Java virtual machine.
      * This method creates one class loader and defines all modules to that
-     * class loader.
+     * class loader. The {@link ClassLoader#getParent() parent} of each class
+     * loader is the given parent class loader. This method works exactly as
+     * specified by the static {@link
+     * #defineModulesWithOneLoader(Configuration,List,ClassLoader)
+     * defineModulesWithOneLoader} method when invoked with this layer as the
+     * parent. In other words, if this layer is {@code thisLayer} then this
+     * method is equivalent to invoking:
+     * <pre> {@code
+     *     Layer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer();
+     * }</pre>
+     *
+     * @param  cf
+     *         The configuration for the layer
+     * @param  parentLoader
+     *         The parent class loader for the class loader created by this
+     *         method; may be {@code null} for the bootstrap class loader
+     *
+     * @return The newly created layer
+     *
+     * @throws IllegalArgumentException
+     *         If the parent of the given configuration is not the configuration
+     *         for this layer
+     * @throws LayerInstantiationException
+     *         If all modules cannot be defined to the same class loader for any
+     *         of the reasons listed above or the layer cannot be created because
+     *         the configuration contains a module named "{@code java.base}" or
+     *         a module with a package name starting with "{@code java.}"
+     * @throws SecurityException
+     *         If {@code RuntimePermission("createClassLoader")} or
+     *         {@code RuntimePermission("getClassLoader")} is denied by
+     *         the security manager
+     *
+     * @see #findLoader
+     */
+    public Layer defineModulesWithOneLoader(Configuration cf,
+                                            ClassLoader parentLoader) {
+        return defineModulesWithOneLoader(cf, List.of(this), parentLoader).layer();
+    }
+
+
+    /**
+     * Creates a new layer, with this layer as its parent, by defining the
+     * modules in the given {@code Configuration} to the Java virtual machine.
+     * Each module is defined to its own {@link ClassLoader} created by this
+     * method. The {@link ClassLoader#getParent() parent} of each class loader
+     * is the given parent class loader. This method works exactly as specified
+     * by the static {@link
+     * #defineModulesWithManyLoaders(Configuration,List,ClassLoader)
+     * defineModulesWithManyLoaders} method when invoked with this layer as the
+     * parent. In other words, if this layer is {@code thisLayer} then this
+     * method is equivalent to invoking:
+     * <pre> {@code
+     *     Layer.defineModulesWithManyLoaders(cf, List.of(thisLayer), parentLoader).layer();
+     * }</pre>
+     *
+     * @param  cf
+     *         The configuration for the layer
+     * @param  parentLoader
+     *         The parent class loader for each of the class loaders created by
+     *         this method; may be {@code null} for the bootstrap class loader
+     *
+     * @return The newly created layer
+     *
+     * @throws IllegalArgumentException
+     *         If the parent of the given configuration is not the configuration
+     *         for this layer
+     * @throws LayerInstantiationException
+     *         If the layer cannot be created because the configuration contains
+     *         a module named "{@code java.base}" or a module with a package
+     *         name starting with "{@code java.}"
+     * @throws SecurityException
+     *         If {@code RuntimePermission("createClassLoader")} or
+     *         {@code RuntimePermission("getClassLoader")} is denied by
+     *         the security manager
+     *
+     * @see #findLoader
+     */
+    public Layer defineModulesWithManyLoaders(Configuration cf,
+                                              ClassLoader parentLoader) {
+        return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer();
+    }
+
+
+    /**
+     * Creates a new layer, with this layer as its parent, by defining the
+     * modules in the given {@code Configuration} to the Java virtual machine.
+     * Each module is mapped, by name, to its class loader by means of the
+     * given function. This method works exactly as specified by the static
+     * {@link #defineModules(Configuration,List,Function) defineModules}
+     * method when invoked with this layer as the parent. In other words, if
+     * this layer is {@code thisLayer} then this method is equivalent to
+     * invoking:
+     * <pre> {@code
+     *     Layer.defineModules(cf, List.of(thisLayer), clf).layer();
+     * }</pre>
+     *
+     * @param  cf
+     *         The configuration for the layer
+     * @param  clf
+     *         The function to map a module name to a class loader
+     *
+     * @return The newly created layer
+     *
+     * @throws IllegalArgumentException
+     *         If the parent of the given configuration is not the configuration
+     *         for this layer
+     * @throws LayerInstantiationException
+     *         If creating the {@code Layer} fails for any of the reasons
+     *         listed above, the layer cannot be created because the
+     *         configuration contains a module named "{@code java.base}",
+     *         a module with a package name starting with "{@code java.}" is
+     *         mapped to a class loader other than the {@link
+     *         ClassLoader#getPlatformClassLoader() platform class loader},
+     *         or the function to map a module name to a class loader returns
+     *         {@code null}
+     * @throws SecurityException
+     *         If {@code RuntimePermission("getClassLoader")} is denied by
+     *         the security manager
+     */
+    public Layer defineModules(Configuration cf,
+                               Function<String, ClassLoader> clf) {
+        return defineModules(cf, List.of(this), clf).layer();
+    }
+
+    /**
+     * Creates a new layer by defining the modules in the given {@code
+     * Configuration} to the Java virtual machine. This method creates one
+     * class loader and defines all modules to that class loader.
      *
      * <p> The class loader created by this method implements <em>direct
      * delegation</em> when loading types from modules. When its {@link
@@ -180,7 +407,7 @@
      * <ul>
      *
      *     <li><p> <em>Overlapping packages</em>: Two or more modules in the
-     *     configuration have the same package (exported or concealed). </p></li>
+     *     configuration have the same package. </p></li>
      *
      *     <li><p> <em>Split delegation</em>: The resulting class loader would
      *     need to delegate to more than one class loader in order to load types
@@ -194,19 +421,22 @@
      *
      * @param  cf
      *         The configuration for the layer
+     * @param  parentLayers
+     *         The list parent layers in search order
      * @param  parentLoader
      *         The parent class loader for the class loader created by this
      *         method; may be {@code null} for the bootstrap class loader
      *
-     * @return The newly created layer
+     * @return A controller that controls the newly created layer
      *
      * @throws IllegalArgumentException
-     *         If the parent of the given configuration is not the configuration
-     *         for this layer
+     *         If the parent configurations do not match the configuration of
+     *         the parent layers, including order
      * @throws LayerInstantiationException
      *         If all modules cannot be defined to the same class loader for any
      *         of the reasons listed above or the layer cannot be created because
-     *         the configuration contains a module named "{@code java.base}"
+     *         the configuration contains a module named "{@code java.base}" or
+     *         a module with a package name starting with "{@code java.}"
      * @throws SecurityException
      *         If {@code RuntimePermission("createClassLoader")} or
      *         {@code RuntimePermission("getClassLoader")} is denied by
@@ -214,29 +444,32 @@
      *
      * @see #findLoader
      */
-    public Layer defineModulesWithOneLoader(Configuration cf,
-                                            ClassLoader parentLoader)
+    public static Controller defineModulesWithOneLoader(Configuration cf,
+                                                        List<Layer> parentLayers,
+                                                        ClassLoader parentLoader)
     {
-        checkConfiguration(cf);
+        List<Layer> parents = new ArrayList<>(parentLayers);
+        checkConfiguration(cf, parents);
+
         checkCreateClassLoaderPermission();
         checkGetClassLoaderPermission();
 
         try {
             Loader loader = new Loader(cf.modules(), parentLoader);
-            loader.initRemotePackageMap(cf, this);
-            return new Layer(cf, this, mn -> loader);
+            loader.initRemotePackageMap(cf, parents);
+            Layer layer =  new Layer(cf, parents, mn -> loader);
+            return new Controller(layer);
         } catch (IllegalArgumentException e) {
             throw new LayerInstantiationException(e.getMessage());
         }
     }
 
-
     /**
-     * Creates a new layer, with this layer as its parent, by defining the
-     * modules in the given {@code Configuration} to the Java virtual machine.
-     * Each module is defined to its own {@link ClassLoader} created by this
-     * method. The {@link ClassLoader#getParent() parent} of each class loader
-     * is the given parent class loader.
+     * Creates a new layer by defining the modules in the given {@code
+     * Configuration} to the Java virtual machine. Each module is defined to
+     * its own {@link ClassLoader} created by this method. The {@link
+     * ClassLoader#getParent() parent} of each class loader is the given parent
+     * class loader.
      *
      * <p> The class loaders created by this method implement <em>direct
      * delegation</em> when loading types from modules. When {@link
@@ -258,18 +491,21 @@
      *
      * @param  cf
      *         The configuration for the layer
+     * @param  parentLayers
+     *         The list parent layers in search order
      * @param  parentLoader
      *         The parent class loader for each of the class loaders created by
      *         this method; may be {@code null} for the bootstrap class loader
      *
-     * @return The newly created layer
+     * @return A controller that controls the newly created layer
      *
      * @throws IllegalArgumentException
-     *         If the parent of the given configuration is not the configuration
-     *         for this layer
+     *         If the parent configurations do not match the configuration of
+     *         the parent layers, including order
      * @throws LayerInstantiationException
      *         If the layer cannot be created because the configuration contains
-     *         a module named "{@code java.base}"
+     *         a module named "{@code java.base}" or a module with a package
+     *         name starting with "{@code java.}"
      * @throws SecurityException
      *         If {@code RuntimePermission("createClassLoader")} or
      *         {@code RuntimePermission("getClassLoader")} is denied by
@@ -277,37 +513,43 @@
      *
      * @see #findLoader
      */
-    public Layer defineModulesWithManyLoaders(Configuration cf,
-                                              ClassLoader parentLoader)
+    public static Controller defineModulesWithManyLoaders(Configuration cf,
+                                                          List<Layer> parentLayers,
+                                                          ClassLoader parentLoader)
     {
-        checkConfiguration(cf);
+        List<Layer> parents = new ArrayList<>(parentLayers);
+        checkConfiguration(cf, parents);
+
         checkCreateClassLoaderPermission();
         checkGetClassLoaderPermission();
 
-        LoaderPool pool = new LoaderPool(cf, this, parentLoader);
+        LoaderPool pool = new LoaderPool(cf, parents, parentLoader);
         try {
-            return new Layer(cf, this, pool::loaderFor);
+            Layer layer = new Layer(cf, parents, pool::loaderFor);
+            return new Controller(layer);
         } catch (IllegalArgumentException e) {
             throw new LayerInstantiationException(e.getMessage());
         }
     }
 
-
     /**
-     * Creates a new layer, with this layer as its parent, by defining the
-     * modules in the given {@code Configuration} to the Java virtual machine.
+     * Creates a new layer by defining the modules in the given {@code
+     * Configuration} to the Java virtual machine.
      * Each module is mapped, by name, to its class loader by means of the
      * given function. The class loader delegation implemented by these class
-     * loaders must respect module readability. In addition, the caller needs
-     * to arrange that the class loaders are ready to load from these module
-     * before there are any attempts to load classes or resources.
+     * loaders must respect module readability. The class loaders should be
+     * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to
+     * avoid deadlocks during class loading. In addition, the entity creating
+     * a new layer with this method should arrange that the class loaders are
+     * ready to load from these module before there are any attempts to load
+     * classes or resources.
      *
      * <p> Creating a {@code Layer} can fail for the following reasons: </p>
      *
      * <ul>
      *
-     *     <li><p> Two or more modules with the same package (exported or
-     *     concealed) are mapped to the same class loader. </p></li>
+     *     <li><p> Two or more modules with the same package are mapped to the
+     *     same class loader. </p></li>
      *
      *     <li><p> A module is mapped to a class loader that already has a
      *     module of the same name defined to it. </p></li>
@@ -328,26 +570,35 @@
      *
      * @param  cf
      *         The configuration for the layer
+     * @param  parentLayers
+     *         The list parent layers in search order
      * @param  clf
      *         The function to map a module name to a class loader
      *
-     * @return The newly created layer
+     * @return A controller that controls the newly created layer
      *
      * @throws IllegalArgumentException
-     *         If the parent of the given configuration is not the configuration
-     *         for this layer
+     *         If the parent configurations do not match the configuration of
+     *         the parent layers, including order
      * @throws LayerInstantiationException
      *         If creating the {@code Layer} fails for any of the reasons
-     *         listed above or the layer cannot be created because the
-     *         configuration contains a module named "{@code java.base}"
+     *         listed above, the layer cannot be created because the
+     *         configuration contains a module named "{@code java.base}",
+     *         a module with a package name starting with "{@code java.}" is
+     *         mapped to a class loader other than the {@link
+     *         ClassLoader#getPlatformClassLoader() platform class loader},
+     *         or the function to map a module name to a class loader returns
+     *         {@code null}
      * @throws SecurityException
      *         If {@code RuntimePermission("getClassLoader")} is denied by
      *         the security manager
      */
-    public Layer defineModules(Configuration cf,
-                               Function<String, ClassLoader> clf)
+    public static Controller defineModules(Configuration cf,
+                                           List<Layer> parentLayers,
+                                           Function<String, ClassLoader> clf)
     {
-        checkConfiguration(cf);
+        List<Layer> parents = new ArrayList<>(parentLayers);
+        checkConfiguration(cf, parents);
         Objects.requireNonNull(clf);
 
         checkGetClassLoaderPermission();
@@ -362,7 +613,8 @@
         }
 
         try {
-            return new Layer(cf, this, clf);
+            Layer layer = new Layer(cf, parents, clf);
+            return new Controller(layer);
         } catch (IllegalArgumentException iae) {
             // IAE is thrown by VM when defining the module fails
             throw new LayerInstantiationException(iae.getMessage());
@@ -370,13 +622,26 @@
     }
 
 
-    private void checkConfiguration(Configuration cf) {
+    /**
+     * Checks that the parent configurations match the configuration of
+     * the parent layers.
+     */
+    private static void checkConfiguration(Configuration cf,
+                                           List<Layer> parentLayers)
+    {
         Objects.requireNonNull(cf);
 
-        Optional<Configuration> oparent = cf.parent();
-        if (!oparent.isPresent() || oparent.get() != this.configuration()) {
-            throw new IllegalArgumentException(
-                    "Parent of configuration != configuration of this Layer");
+        List<Configuration> parentConfigurations = cf.parents();
+        if (parentLayers.size() != parentConfigurations.size())
+            throw new IllegalArgumentException("wrong number of parents");
+
+        int index = 0;
+        for (Layer parent : parentLayers) {
+            if (parent.configuration() != parentConfigurations.get(index)) {
+                throw new IllegalArgumentException(
+                        "Parent of configuration != configuration of this Layer");
+            }
+            index++;
         }
     }
 
@@ -463,18 +728,57 @@
 
 
     /**
-     * Returns this layer's parent unless this is the {@linkplain #empty empty
-     * layer}, which has no parent.
+     * Returns the list of this layer's parents unless this is the
+     * {@linkplain #empty empty layer}, which has no parents and so an
+     * empty list is returned.
      *
-     * @return This layer's parent
+     * @return The list of this layer's parents
      */
-    public Optional<Layer> parent() {
-        return Optional.ofNullable(parent);
+    public List<Layer> parents() {
+        return parents;
     }
 
 
     /**
-     * Returns a set of the modules in this layer.
+     * Returns an ordered stream of layers. The first element is is this layer,
+     * the remaining elements are the parent layers in DFS order.
+     *
+     * @implNote For now, the assumption is that the number of elements will
+     * be very low and so this method does not use a specialized spliterator.
+     */
+    Stream<Layer> layers() {
+        List<Layer> allLayers = this.allLayers;
+        if (allLayers != null)
+            return allLayers.stream();
+
+        allLayers = new ArrayList<>();
+        Set<Layer> visited = new HashSet<>();
+        Deque<Layer> stack = new ArrayDeque<>();
+        visited.add(this);
+        stack.push(this);
+
+        while (!stack.isEmpty()) {
+            Layer layer = stack.pop();
+            allLayers.add(layer);
+
+            // push in reverse order
+            for (int i = layer.parents.size() - 1; i >= 0; i--) {
+                Layer parent = layer.parents.get(i);
+                if (!visited.contains(parent)) {
+                    visited.add(parent);
+                    stack.push(parent);
+                }
+            }
+        }
+
+        this.allLayers = allLayers = Collections.unmodifiableList(allLayers);
+        return allLayers.stream();
+    }
+
+    private volatile List<Layer> allLayers;
+
+    /**
+     * Returns the set of the modules in this layer.
      *
      * @return A possibly-empty unmodifiable set of the modules in this layer
      */
@@ -486,7 +790,11 @@
 
     /**
      * Returns the module with the given name in this layer, or if not in this
-     * layer, the {@linkplain #parent parent} layer.
+     * layer, the {@linkplain #parents parents} layers. Finding a module in
+     * parent layers is equivalent to invoking {@code findModule} on each
+     * parent, in search order, until the module is found or all parents have
+     * been searched. In a <em>tree of layers</em>  then this is equivalent to
+     * a depth-first search.
      *
      * @param  name
      *         The name of the module to find
@@ -496,17 +804,25 @@
      *         parent layer
      */
     public Optional<Module> findModule(String name) {
-        Module m = nameToModule.get(Objects.requireNonNull(name));
+        Objects.requireNonNull(name);
+        Module m = nameToModule.get(name);
         if (m != null)
             return Optional.of(m);
-        return parent().flatMap(l -> l.findModule(name));
+
+        return layers()
+                .skip(1)  // skip this layer
+                .map(l -> l.nameToModule)
+                .filter(map -> map.containsKey(name))
+                .map(map -> map.get(name))
+                .findAny();
     }
 
 
     /**
      * Returns the {@code ClassLoader} for the module with the given name. If
-     * a module of the given name is not in this layer then the {@link #parent}
-     * layer is checked.
+     * a module of the given name is not in this layer then the {@link #parents
+     * parent} layers are searched in the manner specified by {@link
+     * #findModule(String) findModule}.
      *
      * <p> If there is a security manager then its {@code checkPermission}
      * method is called with a {@code RuntimePermission("getClassLoader")}
@@ -527,20 +843,32 @@
      * @throws SecurityException if denied by the security manager
      */
     public ClassLoader findLoader(String name) {
-        Module m = nameToModule.get(Objects.requireNonNull(name));
-        if (m != null)
-            return m.getClassLoader();
-        Optional<Layer> ol = parent();
-        if (ol.isPresent())
-            return ol.get().findLoader(name);
-        throw new IllegalArgumentException("Module " + name
-                                           + " not known to this layer");
+        Optional<Module> om = findModule(name);
+
+        // can't use map(Module::getClassLoader) as class loader can be null
+        if (om.isPresent()) {
+            return om.get().getClassLoader();
+        } else {
+            throw new IllegalArgumentException("Module " + name
+                                               + " not known to this layer");
+        }
     }
 
+    /**
+     * Returns a string describing this layer.
+     *
+     * @return A possibly empty string describing this layer
+     */
+    @Override
+    public String toString() {
+        return modules().stream()
+                .map(Module::getName)
+                .collect(Collectors.joining(", "));
+    }
 
     /**
      * Returns the <em>empty</em> layer. There are no modules in the empty
-     * layer. It has no parent.
+     * layer. It has no parents.
      *
      * @return The empty layer
      */
@@ -572,39 +900,12 @@
         if (servicesCatalog != null)
             return servicesCatalog;
 
-        Map<String, Set<ServiceProvider>> map = new HashMap<>();
-        for (Module m : nameToModule.values()) {
-            ModuleDescriptor descriptor = m.getDescriptor();
-            for (Provides provides : descriptor.provides().values()) {
-                String service = provides.service();
-                Set<ServiceProvider> providers
-                    = map.computeIfAbsent(service, k -> new HashSet<>());
-                for (String pn : provides.providers()) {
-                    providers.add(new ServiceProvider(m, pn));
-                }
-            }
-        }
-
-        ServicesCatalog catalog = new ServicesCatalog() {
-            @Override
-            public void register(Module module) {
-                throw new UnsupportedOperationException();
-            }
-            @Override
-            public Set<ServiceProvider> findServices(String service) {
-                Set<ServiceProvider> providers = map.get(service);
-                if (providers == null) {
-                    return Collections.emptySet();
-                } else {
-                    return Collections.unmodifiableSet(providers);
-                }
-            }
-        };
-
         synchronized (this) {
             servicesCatalog = this.servicesCatalog;
             if (servicesCatalog == null) {
-                this.servicesCatalog = servicesCatalog = catalog;
+                servicesCatalog = ServicesCatalog.create();
+                nameToModule.values().forEach(servicesCatalog::register);
+                this.servicesCatalog = servicesCatalog;
             }
         }
 
@@ -612,4 +913,36 @@
     }
 
     private volatile ServicesCatalog servicesCatalog;
+
+
+    /**
+     * Record that this layer has at least one module defined to the given
+     * class loader.
+     */
+    void bindToLoader(ClassLoader loader) {
+        // CLV.computeIfAbsent(loader, (cl, clv) -> new CopyOnWriteArrayList<>())
+        List<Layer> list = CLV.get(loader);
+        if (list == null) {
+            list = new CopyOnWriteArrayList<>();
+            List<Layer> previous = CLV.putIfAbsent(loader, list);
+            if (previous != null) list = previous;
+        }
+        list.add(this);
+    }
+
+    /**
+     * Returns a stream of the layers that have at least one module defined to
+     * the given class loader.
+     */
+    static Stream<Layer> layers(ClassLoader loader) {
+        List<Layer> list = CLV.get(loader);
+        if (list != null) {
+            return list.stream();
+        } else {
+            return Stream.empty();
+        }
+    }
+
+    // the list of layers with modules defined to a class loader
+    private static final ClassLoaderValue<List<Layer>> CLV = new ClassLoaderValue<>();
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
index 26e4724..29f21cc 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
@@ -27,15 +27,18 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.annotation.Annotation;
 import java.lang.module.Configuration;
 import java.lang.module.ModuleReference;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
-import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Version;
 import java.lang.module.ResolvedModule;
 import java.net.URI;
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -49,9 +52,17 @@
 
 import jdk.internal.loader.BuiltinClassLoader;
 import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.ResourceHelper;
+import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.misc.JavaLangReflectModuleAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.module.ServicesCatalog;
+import jdk.internal.org.objectweb.asm.AnnotationVisitor;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 import sun.security.util.SecurityConstants;
@@ -83,7 +94,7 @@
  * @see java.lang.Class#getModule
  */
 
-public final class Module {
+public final class Module implements AnnotatedElement {
 
     // the layer that contains this module, can be null
     private final Layer layer;
@@ -113,6 +124,10 @@
 
         // define module to VM
 
+        boolean isOpen = descriptor.isOpen();
+        Version version = descriptor.version().orElse(null);
+        String vs = Objects.toString(version, null);
+        String loc = Objects.toString(uri, null);
         Set<String> packages = descriptor.packages();
         int n = packages.size();
         String[] array = new String[n];
@@ -120,11 +135,7 @@
         for (String pn : packages) {
             array[i++] = pn.replace('.', '/');
         }
-        Version version = descriptor.version().orElse(null);
-        String vs = Objects.toString(version, null);
-        String loc = Objects.toString(uri, null);
-
-        defineModule0(this, vs, loc, array);
+        defineModule0(this, isOpen, vs, loc, array);
     }
 
 
@@ -240,24 +251,24 @@
 
     // --
 
-    // the special Module to mean reads or exported to "all unnamed modules"
+    // special Module to mean "all unnamed modules"
     private static final Module ALL_UNNAMED_MODULE = new Module(null);
 
-    // special Module to mean exported to "everyone"
+    // special Module to mean "everyone"
     private static final Module EVERYONE_MODULE = new Module(null);
 
-    // exported to all modules
-    private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
+    // set contains EVERYONE_MODULE, used when a package is opened or
+    // exported unconditionally
+    private static final Set<Module> EVERYONE_SET = Set.of(EVERYONE_MODULE);
 
 
     // -- readability --
 
-    // the modules that this module permanently reads
-    // (will be final when the modules are defined in reverse topology order)
+    // the modules that this module reads
     private volatile Set<Module> reads;
 
     // additional module (2nd key) that some module (1st key) reflectively reads
-    private static final WeakPairMap<Module, Module, Boolean> transientReads
+    private static final WeakPairMap<Module, Module, Boolean> reflectivelyReads
         = new WeakPairMap<>();
 
 
@@ -293,13 +304,13 @@
         }
 
         // check if this module reads the other module reflectively
-        if (transientReads.containsKeyPair(this, other))
+        if (reflectivelyReads.containsKeyPair(this, other))
             return true;
 
         // if other is an unnamed module then check if this module reads
         // all unnamed modules
         if (!other.isNamed()
-            && transientReads.containsKeyPair(this, ALL_UNNAMED_MODULE))
+            && reflectivelyReads.containsKeyPair(this, ALL_UNNAMED_MODULE))
             return true;
 
         return false;
@@ -309,9 +320,13 @@
      * If the caller's module is this module then update this module to read
      * the given module.
      *
-     * This method is a no-op if {@code other} is this module (all modules can
-     * read themselves) or this module is an unnamed module (as unnamed modules
-     * read all modules).
+     * This method is a no-op if {@code other} is this module (all modules read
+     * themselves), this module is an unnamed module (as unnamed modules read
+     * all modules), or this module already reads {@code other}.
+     *
+     * @implNote <em>Read edges</em> added by this method are <em>weak</em> and
+     * do not prevent {@code other} from being GC'ed when this module is
+     * strongly reachable.
      *
      * @param  other
      *         The other module
@@ -381,30 +396,39 @@
         }
 
         // add reflective read
-        transientReads.putIfAbsent(this, other, Boolean.TRUE);
+        reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
     }
 
 
-    // -- exports --
+    // -- exported and open packages --
 
-    // the packages that are permanently exported
-    // (will be final when the modules are defined in reverse topology order)
-    private volatile Map<String, Set<Module>> exports;
+    // the packages are open to other modules, can be null
+    // if the value contains EVERYONE_MODULE then the package is open to all
+    private volatile Map<String, Set<Module>> openPackages;
 
-    // additional exports added at run-time
-    // this module (1st key), other module (2nd key), exported packages (value)
+    // the packages that are exported, can be null
+    // if the value contains EVERYONE_MODULE then the package is exported to all
+    private volatile Map<String, Set<Module>> exportedPackages;
+
+    // additional exports or opens added at run-time
+    // this module (1st key), other module (2nd key)
+    // (package name, open?) (value)
     private static final WeakPairMap<Module, Module, Map<String, Boolean>>
-        transientExports = new WeakPairMap<>();
+        reflectivelyExports = new WeakPairMap<>();
 
 
     /**
      * Returns {@code true} if this module exports the given package to at
      * least the given module.
      *
-     * <p> This method always return {@code true} when invoked on an unnamed
+     * <p> This method returns {@code true} if invoked to test if a package in
+     * this module is exported to itself. It always returns {@code true} when
+     * invoked on an unnamed module. A package that is {@link #isOpen open} to
+     * the given module is considered exported to that module at run-time and
+     * so this method returns {@code true} if the package is open to the given
      * module. </p>
      *
-     * <p> This method does not check if the given module reads this module </p>
+     * <p> This method does not check if the given module reads this module. </p>
      *
      * @param  pn
      *         The package name
@@ -413,93 +437,196 @@
      *
      * @return {@code true} if this module exports the package to at least the
      *         given module
+     *
+     * @see ModuleDescriptor#exports()
+     * @see #addExports(String,Module)
      */
     public boolean isExported(String pn, Module other) {
         Objects.requireNonNull(pn);
         Objects.requireNonNull(other);
-        return implIsExported(pn, other);
+        return implIsExportedOrOpen(pn, other, /*open*/false);
+    }
+
+    /**
+     * Returns {@code true} if this module has <em>opened</em> a package to at
+     * least the given module.
+     *
+     * <p> This method returns {@code true} if invoked to test if a package in
+     * this module is open to itself. It returns {@code true} when invoked on an
+     * {@link ModuleDescriptor#isOpen open} module with a package in the module.
+     * It always returns {@code true} when invoked on an unnamed module. </p>
+     *
+     * <p> This method does not check if the given module reads this module. </p>
+     *
+     * @param  pn
+     *         The package name
+     * @param  other
+     *         The other module
+     *
+     * @return {@code true} if this module has <em>opened</em> the package
+     *         to at least the given module
+     *
+     * @see ModuleDescriptor#opens()
+     * @see #addOpens(String,Module)
+     * @see AccessibleObject#setAccessible(boolean)
+     * @see java.lang.invoke.MethodHandles#privateLookupIn
+     */
+    public boolean isOpen(String pn, Module other) {
+        Objects.requireNonNull(pn);
+        Objects.requireNonNull(other);
+        return implIsExportedOrOpen(pn, other, /*open*/true);
     }
 
     /**
      * Returns {@code true} if this module exports the given package
      * unconditionally.
      *
-     * <p> This method always return {@code true} when invoked on an unnamed
-     * module. </p>
+     * <p> This method always returns {@code true} when invoked on an unnamed
+     * module. A package that is {@link #isOpen(String) opened} unconditionally
+     * is considered exported unconditionally at run-time and so this method
+     * returns {@code true} if the package is opened unconditionally. </p>
      *
-     * <p> This method does not check if the given module reads this module </p>
+     * <p> This method does not check if the given module reads this module. </p>
      *
      * @param  pn
      *         The package name
      *
      * @return {@code true} if this module exports the package unconditionally
+     *
+     * @see ModuleDescriptor#exports()
      */
     public boolean isExported(String pn) {
         Objects.requireNonNull(pn);
-        return implIsExported(pn, EVERYONE_MODULE);
+        return implIsExportedOrOpen(pn, EVERYONE_MODULE, /*open*/false);
     }
 
     /**
-     * Returns {@code true} if this module exports the given package to the
-     * given module. If the other module is {@code EVERYONE_MODULE} then
-     * this method tests if the package is exported unconditionally.
+     * Returns {@code true} if this module has <em>opened</em> a package
+     * unconditionally.
+     *
+     * <p> This method always returns {@code true} when invoked on an unnamed
+     * module. Additionally, it always returns {@code true} when invoked on an
+     * {@link ModuleDescriptor#isOpen open} module with a package in the
+     * module. </p>
+     *
+     * <p> This method does not check if the given module reads this module. </p>
+     *
+     * @param  pn
+     *         The package name
+     *
+     * @return {@code true} if this module has <em>opened</em> the package
+     *         unconditionally
+     *
+     * @see ModuleDescriptor#opens()
      */
-    private boolean implIsExported(String pn, Module other) {
+    public boolean isOpen(String pn) {
+        Objects.requireNonNull(pn);
+        return implIsExportedOrOpen(pn, EVERYONE_MODULE, /*open*/true);
+    }
 
-        // all packages are exported by unnamed modules
+
+    /**
+     * Returns {@code true} if this module exports or opens the given package
+     * to the given module. If the other module is {@code EVERYONE_MODULE} then
+     * this method tests if the package is exported or opened unconditionally.
+     */
+    private boolean implIsExportedOrOpen(String pn, Module other, boolean open) {
+        // all packages in unnamed modules are open
         if (!isNamed())
             return true;
 
-        // exported via module declaration/descriptor
-        if (isExportedPermanently(pn, other))
+        // all packages are exported/open to self
+        if (other == this && containsPackage(pn))
             return true;
 
-        // exported via addExports
-        if (isExportedReflectively(pn, other))
+        // all packages in open modules are open
+        if (descriptor.isOpen())
+            return containsPackage(pn);
+
+        // exported/opened via module declaration/descriptor
+        if (isStaticallyExportedOrOpen(pn, other, open))
             return true;
 
-        // not exported or not exported to other
+        // exported via addExports/addOpens
+        if (isReflectivelyExportedOrOpen(pn, other, open))
+            return true;
+
+        // not exported or open to other
         return false;
     }
 
     /**
-     * Returns {@code true} if this module permanently exports the given
-     * package to the given module.
+     * Returns {@code true} if this module exports or opens a package to
+     * the given module via its module declaration.
      */
-    private boolean isExportedPermanently(String pn, Module other) {
-        Map<String, Set<Module>> exports = this.exports;
-        if (exports != null) {
-            Set<Module> targets = exports.get(pn);
-
-            if ((targets != null)
-                && (targets.contains(other) || targets.contains(EVERYONE_MODULE)))
-                return true;
+    private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
+        // package is open to everyone or <other>
+        Map<String, Set<Module>> openPackages = this.openPackages;
+        if (openPackages != null) {
+            Set<Module> targets = openPackages.get(pn);
+            if (targets != null) {
+                if (targets.contains(EVERYONE_MODULE))
+                    return true;
+                if (other != EVERYONE_MODULE && targets.contains(other))
+                    return true;
+            }
         }
+
+        if (!open) {
+            // package is exported to everyone or <other>
+            Map<String, Set<Module>> exportedPackages = this.exportedPackages;
+            if (exportedPackages != null) {
+                Set<Module> targets = exportedPackages.get(pn);
+                if (targets != null) {
+                    if (targets.contains(EVERYONE_MODULE))
+                        return true;
+                    if (other != EVERYONE_MODULE && targets.contains(other))
+                        return true;
+                }
+            }
+        }
+
         return false;
     }
 
+
     /**
-     * Returns {@code true} if this module reflectively exports the given
+     * Returns {@code true} if this module reflectively exports or opens given
      * package package to the given module.
      */
-    private boolean isExportedReflectively(String pn, Module other) {
-        // exported to all modules
-        Map<String, ?> exports = transientExports.get(this, EVERYONE_MODULE);
-        if (exports != null && exports.containsKey(pn))
-            return true;
+    private boolean isReflectivelyExportedOrOpen(String pn, Module other, boolean open) {
+        // exported or open to all modules
+        Map<String, Boolean> exports = reflectivelyExports.get(this, EVERYONE_MODULE);
+        if (exports != null) {
+            Boolean b = exports.get(pn);
+            if (b != null) {
+                boolean isOpen = b.booleanValue();
+                if (!open || isOpen) return true;
+            }
+        }
 
         if (other != EVERYONE_MODULE) {
 
-            // exported to other
-            exports = transientExports.get(this, other);
-            if (exports != null && exports.containsKey(pn))
-                return true;
+            // exported or open to other
+            exports = reflectivelyExports.get(this, other);
+            if (exports != null) {
+                Boolean b = exports.get(pn);
+                if (b != null) {
+                    boolean isOpen = b.booleanValue();
+                    if (!open || isOpen) return true;
+                }
+            }
 
-            // other is an unnamed module && exported to all unnamed
+            // other is an unnamed module && exported or open to all unnamed
             if (!other.isNamed()) {
-                exports = transientExports.get(this, ALL_UNNAMED_MODULE);
-                if (exports != null && exports.containsKey(pn))
-                    return true;
+                exports = reflectivelyExports.get(this, ALL_UNNAMED_MODULE);
+                if (exports != null) {
+                    Boolean b = exports.get(pn);
+                    if (b != null) {
+                        boolean isOpen = b.booleanValue();
+                        if (!open || isOpen) return true;
+                    }
+                }
             }
 
         }
@@ -510,11 +637,11 @@
 
     /**
      * If the caller's module is this module then update this module to export
-     * package {@code pn} to the given module.
+     * the given package to the given module.
      *
-     * <p> This method has no effect if the package is already exported to the
-     * given module. It also has no effect if invoked on an unnamed module (as
-     * unnamed modules export all packages). </p>
+     * <p> This method has no effect if the package is already exported (or
+     * <em>open</em>) to the given module. It also has no effect if
+     * invoked on an {@link ModuleDescriptor#isOpen open} module. </p>
      *
      * @param  pn
      *         The package name
@@ -528,6 +655,8 @@
      *         package {@code pn} is not a package in this module
      * @throws IllegalStateException
      *         If this is a named module and the caller is not this module
+     *
+     * @see #isExported(String,Module)
      */
     @CallerSensitive
     public Module addExports(String pn, Module other) {
@@ -535,18 +664,66 @@
             throw new IllegalArgumentException("package is null");
         Objects.requireNonNull(other);
 
-        if (isNamed()) {
+        if (isNamed() && !descriptor.isOpen()) {
             Module caller = Reflection.getCallerClass().getModule();
             if (caller != this) {
                 throw new IllegalStateException(caller + " != " + this);
             }
-            implAddExports(pn, other, true);
+            implAddExportsOrOpens(pn, other, /*open*/false, /*syncVM*/true);
         }
 
         return this;
     }
 
     /**
+     * If the caller's module is this module then update this module to
+     * <em>open</em> the given package to the given module.
+     * Opening a package with this method allows all types in the package,
+     * and all their members, not just public types and their public members,
+     * to be reflected on by the given module when using APIs that support
+     * private access or a way to bypass or suppress default Java language
+     * access control checks.
+     *
+     * <p> This method has no effect if the package is already <em>open</em>
+     * to the given module. It also has no effect if invoked on an {@link
+     * ModuleDescriptor#isOpen open} module. </p>
+     *
+     * @param  pn
+     *         The package name
+     * @param  other
+     *         The module
+     *
+     * @return this module
+     *
+     * @throws IllegalArgumentException
+     *         If {@code pn} is {@code null}, or this is a named module and the
+     *         package {@code pn} is not a package in this module
+     * @throws IllegalStateException
+     *         If this is a named module and the caller is not this module
+     *
+     * @see #isOpen(String,Module)
+     * @see AccessibleObject#setAccessible(boolean)
+     * @see java.lang.invoke.MethodHandles#privateLookupIn
+     */
+    @CallerSensitive
+    public Module addOpens(String pn, Module other) {
+        if (pn == null)
+            throw new IllegalArgumentException("package is null");
+        Objects.requireNonNull(other);
+
+        if (isNamed() && !descriptor.isOpen()) {
+            Module caller = Reflection.getCallerClass().getModule();
+            if (caller != this) {
+                throw new IllegalStateException(caller + " != " + this);
+            }
+            implAddExportsOrOpens(pn, other, /*open*/true, /*syncVM*/true);
+        }
+
+        return this;
+    }
+
+
+    /**
      * Updates the exports so that package {@code pn} is exported to module
      * {@code other} but without notifying the VM.
      *
@@ -555,7 +732,7 @@
     void implAddExportsNoSync(String pn, Module other) {
         if (other == null)
             other = EVERYONE_MODULE;
-        implAddExports(pn.replace('/', '.'), other, false);
+        implAddExportsOrOpens(pn.replace('/', '.'), other, false, false);
     }
 
     /**
@@ -565,25 +742,36 @@
      * @apiNote This method is for white-box testing.
      */
     void implAddExports(String pn, Module other) {
-        implAddExports(pn, other, true);
+        implAddExportsOrOpens(pn, other, false, true);
     }
 
     /**
-     * Updates the exports so that package {@code pn} is exported to module
-     * {@code other}.
+     * Updates the module to open package {@code pn} to module {@code other}.
+     *
+     * @apiNote This method is for white-box tests and jtreg
+     */
+    void implAddOpens(String pn, Module other) {
+        implAddExportsOrOpens(pn, other, true, true);
+    }
+
+    /**
+     * Updates a module to export or open a module to another module.
      *
      * If {@code syncVM} is {@code true} then the VM is notified.
      */
-    private void implAddExports(String pn, Module other, boolean syncVM) {
+    private void implAddExportsOrOpens(String pn,
+                                       Module other,
+                                       boolean open,
+                                       boolean syncVM) {
         Objects.requireNonNull(other);
         Objects.requireNonNull(pn);
 
-        // unnamed modules export all packages
-        if (!isNamed())
+        // all packages are open in unnamed and open modules
+        if (!isNamed() || descriptor.isOpen())
             return;
 
-        // nothing to do if already exported to other
-        if (implIsExported(pn, other))
+        // nothing to do if already exported/open to other
+        if (implIsExportedOrOpen(pn, other, open))
             return;
 
         // can only export a package in the module
@@ -604,18 +792,23 @@
             }
         }
 
-        // add package name to transientExports if absent
-        transientExports
+        // add package name to reflectivelyExports if absent
+        Map<String, Boolean> map = reflectivelyExports
             .computeIfAbsent(this, other,
-                             (_this, _other) -> new ConcurrentHashMap<>())
-            .putIfAbsent(pn, Boolean.TRUE);
+                             (m1, m2) -> new ConcurrentHashMap<>());
+
+        if (open) {
+            map.put(pn, Boolean.TRUE);  // may need to promote from FALSE to TRUE
+        } else {
+            map.putIfAbsent(pn, Boolean.FALSE);
+        }
     }
 
 
     // -- services --
 
     // additional service type (2nd key) that some module (1st key) uses
-    private static final WeakPairMap<Module, Class<?>, Boolean> transientUses
+    private static final WeakPairMap<Module, Class<?>, Boolean> reflectivelyUses
         = new WeakPairMap<>();
 
     /**
@@ -624,13 +817,13 @@
      * for use by frameworks that invoke {@link java.util.ServiceLoader
      * ServiceLoader} on behalf of other modules or where the framework is
      * passed a reference to the service type by other code. This method is
-     * a no-op when invoked on an unnamed module.
+     * a no-op when invoked on an unnamed module or an automatic module.
      *
      * <p> This method does not cause {@link
      * Configuration#resolveRequiresAndUses resolveRequiresAndUses} to be
      * re-run. </p>
      *
-     * @param  st
+     * @param  service
      *         The service type
      *
      * @return this module
@@ -642,39 +835,45 @@
      * @see ModuleDescriptor#uses()
      */
     @CallerSensitive
-    public Module addUses(Class<?> st) {
-        Objects.requireNonNull(st);
+    public Module addUses(Class<?> service) {
+        Objects.requireNonNull(service);
 
-        if (isNamed()) {
-
+        if (isNamed() && !descriptor.isAutomatic()) {
             Module caller = Reflection.getCallerClass().getModule();
             if (caller != this) {
                 throw new IllegalStateException(caller + " != " + this);
             }
-
-            if (!canUse(st)) {
-                transientUses.putIfAbsent(this, st, Boolean.TRUE);
-            }
-
+            implAddUses(service);
         }
 
         return this;
     }
 
     /**
+     * Update this module to add a service dependence on the given service
+     * type.
+     */
+    void implAddUses(Class<?> service) {
+        if (!canUse(service)) {
+            reflectivelyUses.putIfAbsent(this, service, Boolean.TRUE);
+        }
+    }
+
+
+    /**
      * Indicates if this module has a service dependence on the given service
      * type. This method always returns {@code true} when invoked on an unnamed
-     * module.
+     * module or an automatic module.
      *
-     * @param  st
+     * @param  service
      *         The service type
      *
      * @return {@code true} if this module uses service type {@code st}
      *
      * @see #addUses(Class)
      */
-    public boolean canUse(Class<?> st) {
-        Objects.requireNonNull(st);
+    public boolean canUse(Class<?> service) {
+        Objects.requireNonNull(service);
 
         if (!isNamed())
             return true;
@@ -683,11 +882,11 @@
             return true;
 
         // uses was declared
-        if (descriptor.uses().contains(st.getName()))
+        if (descriptor.uses().contains(service.getName()))
             return true;
 
         // uses added via addUses
-        return transientUses.containsKeyPair(this, st);
+        return reflectivelyUses.containsKeyPair(this, service);
     }
 
 
@@ -780,8 +979,12 @@
      * If {@code syncVM} is {@code true} then the VM is notified.
      */
     private void implAddPackage(String pn, boolean syncVM) {
-        if (pn.length() == 0)
-            throw new IllegalArgumentException("<unnamed> package not allowed");
+        if (!isNamed())
+            throw new InternalError("adding package to unnamed module?");
+        if (descriptor.isOpen())
+            throw new InternalError("adding package to open module?");
+        if (pn.isEmpty())
+            throw new InternalError("adding <unnamed> package to module?");
 
         if (descriptor.packages().contains(pn)) {
             // already in module
@@ -822,28 +1025,7 @@
     // -- creating Module objects --
 
     /**
-     * Find the runtime Module corresponding to the given ResolvedModule
-     * in the given parent Layer (or its parents).
-     */
-    private static Module find(ResolvedModule resolvedModule, Layer layer) {
-        Configuration cf = resolvedModule.configuration();
-        String dn = resolvedModule.name();
-
-        Module m = null;
-        while (layer != null) {
-            if (layer.configuration() == cf) {
-                Optional<Module> om = layer.findModule(dn);
-                m = om.get();
-                assert m.getLayer() == layer;
-                break;
-            }
-            layer = layer.parent().orElse(null);
-        }
-        return m;
-    }
-
-    /**
-     * Defines each of the module in the given configuration to the runtime.
+     * Defines all module in a configuration to the runtime.
      *
      * @return a map of module name to runtime {@code Module}
      *
@@ -854,26 +1036,40 @@
                                              Function<String, ClassLoader> clf,
                                              Layer layer)
     {
-        Map<String, Module> modules = new HashMap<>();
-        Map<String, ClassLoader> loaders = new HashMap<>();
+        Map<String, Module> nameToModule = new HashMap<>();
+        Map<String, ClassLoader> moduleToLoader = new HashMap<>();
+
+        boolean isBootLayer = (Layer.boot() == null);
+        Set<ClassLoader> loaders = new HashSet<>();
+
+        // map each module to a class loader
+        for (ResolvedModule resolvedModule : cf.modules()) {
+            String name = resolvedModule.name();
+            ClassLoader loader = clf.apply(name);
+            if (loader != null) {
+                moduleToLoader.put(name, loader);
+                loaders.add(loader);
+            } else if (!isBootLayer) {
+                throw new IllegalArgumentException("loader can't be 'null'");
+            }
+        }
 
         // define each module in the configuration to the VM
         for (ResolvedModule resolvedModule : cf.modules()) {
             ModuleReference mref = resolvedModule.reference();
             ModuleDescriptor descriptor = mref.descriptor();
             String name = descriptor.name();
-            ClassLoader loader = clf.apply(name);
             URI uri = mref.location().orElse(null);
-
+            ClassLoader loader = moduleToLoader.get(resolvedModule.name());
             Module m;
-            if (loader == null && name.equals("java.base") && Layer.boot() == null) {
+            if (loader == null && isBootLayer && name.equals("java.base")) {
+                // java.base is already defined to the VM
                 m = Object.class.getModule();
             } else {
                 m = new Module(layer, loader, descriptor, uri);
             }
-
-            modules.put(name, m);
-            loaders.put(name, loader);
+            nameToModule.put(name, m);
+            moduleToLoader.put(name, loader);
         }
 
         // setup readability and exports
@@ -882,20 +1078,24 @@
             ModuleDescriptor descriptor = mref.descriptor();
 
             String mn = descriptor.name();
-            Module m = modules.get(mn);
+            Module m = nameToModule.get(mn);
             assert m != null;
 
             // reads
             Set<Module> reads = new HashSet<>();
-            for (ResolvedModule d : resolvedModule.reads()) {
-                Module m2;
-                if (d.configuration() == cf) {
-                    String dn = d.reference().descriptor().name();
-                    m2 = modules.get(dn);
-                    assert m2 != null;
+            for (ResolvedModule other : resolvedModule.reads()) {
+                Module m2 = null;
+                if (other.configuration() == cf) {
+                    String dn = other.reference().descriptor().name();
+                    m2 = nameToModule.get(dn);
                 } else {
-                    m2 = find(d, layer.parent().orElse(null));
+                    for (Layer parent: layer.parents()) {
+                        m2 = findModule(parent, other);
+                        if (m2 != null)
+                            break;
+                    }
                 }
+                assert m2 != null;
 
                 reads.add(m2);
 
@@ -904,64 +1104,273 @@
             }
             m.reads = reads;
 
-            // automatic modules reads all unnamed modules
+            // automatic modules read all unnamed modules
             if (descriptor.isAutomatic()) {
                 m.implAddReads(ALL_UNNAMED_MODULE, true);
             }
 
-            // exports
-            Map<String, Set<Module>> exports = new HashMap<>();
-            for (Exports export : descriptor.exports()) {
-                String source = export.source();
+            // exports and opens
+            initExportsAndOpens(descriptor, nameToModule, m);
+        }
+
+        // register the modules in the boot layer
+        if (isBootLayer) {
+            for (ResolvedModule resolvedModule : cf.modules()) {
+                ModuleReference mref = resolvedModule.reference();
+                ModuleDescriptor descriptor = mref.descriptor();
+                if (!descriptor.provides().isEmpty()) {
+                    String name = descriptor.name();
+                    Module m = nameToModule.get(name);
+                    ClassLoader loader = moduleToLoader.get(name);
+                    ServicesCatalog catalog;
+                    if (loader == null) {
+                        catalog = BootLoader.getServicesCatalog();
+                    } else {
+                        catalog = ServicesCatalog.getServicesCatalog(loader);
+                    }
+                    catalog.register(m);
+                }
+            }
+        }
+
+        // record that there is a layer with modules defined to the class loader
+        for (ClassLoader loader : loaders) {
+            layer.bindToLoader(loader);
+        }
+
+        return nameToModule;
+    }
+
+
+    /**
+     * Find the runtime Module corresponding to the given ResolvedModule
+     * in the given parent layer (or its parents).
+     */
+    private static Module findModule(Layer parent, ResolvedModule resolvedModule) {
+        Configuration cf = resolvedModule.configuration();
+        String dn = resolvedModule.name();
+        return parent.layers()
+                .filter(l -> l.configuration() == cf)
+                .findAny()
+                .map(layer -> {
+                    Optional<Module> om = layer.findModule(dn);
+                    assert om.isPresent() : dn + " not found in layer";
+                    Module m = om.get();
+                    assert m.getLayer() == layer : m + " not in expected layer";
+                    return m;
+                })
+                .orElse(null);
+    }
+
+    /**
+     * Initialize the maps of exported and open packages for module m.
+     */
+    private static void initExportsAndOpens(ModuleDescriptor descriptor,
+                                            Map<String, Module> nameToModule,
+                                            Module m)
+    {
+        // The VM doesn't know about open modules so need to export all packages
+        if (descriptor.isOpen()) {
+            assert descriptor.opens().isEmpty();
+            for (String source : descriptor.packages()) {
                 String sourceInternalForm = source.replace('.', '/');
+                addExportsToAll0(m, sourceInternalForm);
+            }
+            return;
+        }
 
-                if (export.isQualified()) {
+        Map<String, Set<Module>> openPackages = new HashMap<>();
+        Map<String, Set<Module>> exportedPackages = new HashMap<>();
 
-                    // qualified export
-                    Set<Module> targets = new HashSet<>();
-                    for (String target : export.targets()) {
-                        // only export to modules that are in this configuration
-                        Module m2 = modules.get(target);
-                        if (m2 != null) {
-                            targets.add(m2);
+        // process the open packages first
+        for (Opens opens : descriptor.opens()) {
+            String source = opens.source();
+            String sourceInternalForm = source.replace('.', '/');
+
+            if (opens.isQualified()) {
+                // qualified opens
+                Set<Module> targets = new HashSet<>();
+                for (String target : opens.targets()) {
+                    // only open to modules that are in this configuration
+                    Module m2 = nameToModule.get(target);
+                    if (m2 != null) {
+                        addExports0(m, sourceInternalForm, m2);
+                        targets.add(m2);
+                    }
+                }
+                if (!targets.isEmpty()) {
+                    openPackages.put(source, targets);
+                }
+            } else {
+                // unqualified opens
+                addExportsToAll0(m, sourceInternalForm);
+                openPackages.put(source, EVERYONE_SET);
+            }
+        }
+
+        // next the exports, skipping exports when the package is open
+        for (Exports exports : descriptor.exports()) {
+            String source = exports.source();
+            String sourceInternalForm = source.replace('.', '/');
+
+            // skip export if package is already open to everyone
+            Set<Module> openToTargets = openPackages.get(source);
+            if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE))
+                continue;
+
+            if (exports.isQualified()) {
+                // qualified exports
+                Set<Module> targets = new HashSet<>();
+                for (String target : exports.targets()) {
+                    // only export to modules that are in this configuration
+                    Module m2 = nameToModule.get(target);
+                    if (m2 != null) {
+                        // skip qualified export if already open to m2
+                        if (openToTargets == null || !openToTargets.contains(m2)) {
                             addExports0(m, sourceInternalForm, m2);
+                            targets.add(m2);
                         }
                     }
-                    if (!targets.isEmpty()) {
-                        exports.put(source, targets);
-                    }
-
-                } else {
-
-                    // unqualified export
-                    exports.put(source, EVERYONE);
-                    addExportsToAll0(m, sourceInternalForm);
                 }
-            }
-            m.exports = exports;
-        }
-
-        // register the modules in the service catalog if they provide services
-        for (ResolvedModule resolvedModule : cf.modules()) {
-            ModuleReference mref = resolvedModule.reference();
-            ModuleDescriptor descriptor = mref.descriptor();
-            Map<String, Provides> services = descriptor.provides();
-            if (!services.isEmpty()) {
-                String name = descriptor.name();
-                Module m = modules.get(name);
-                ClassLoader loader = loaders.get(name);
-                ServicesCatalog catalog;
-                if (loader == null) {
-                    catalog = BootLoader.getServicesCatalog();
-                } else {
-                    catalog = SharedSecrets.getJavaLangAccess()
-                                           .createOrGetServicesCatalog(loader);
+                if (!targets.isEmpty()) {
+                    exportedPackages.put(source, targets);
                 }
-                catalog.register(m);
+
+            } else {
+                // unqualified exports
+                addExportsToAll0(m, sourceInternalForm);
+                exportedPackages.put(source, EVERYONE_SET);
             }
         }
 
-        return modules;
+        if (!openPackages.isEmpty())
+            m.openPackages = openPackages;
+        if (!exportedPackages.isEmpty())
+            m.exportedPackages = exportedPackages;
+    }
+
+
+    // -- annotations --
+
+    /**
+     * {@inheritDoc}
+     * This method returns {@code null} when invoked on an unnamed module.
+     */
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+        return moduleInfoClass().getDeclaredAnnotation(annotationClass);
+    }
+
+    /**
+     * {@inheritDoc}
+     * This method returns an empty array when invoked on an unnamed module.
+     */
+    @Override
+    public Annotation[] getAnnotations() {
+        return moduleInfoClass().getAnnotations();
+    }
+
+    /**
+     * {@inheritDoc}
+     * This method returns an empty array when invoked on an unnamed module.
+     */
+    @Override
+    public Annotation[] getDeclaredAnnotations() {
+        return moduleInfoClass().getDeclaredAnnotations();
+    }
+
+    // cached class file with annotations
+    private volatile Class<?> moduleInfoClass;
+
+    private Class<?> moduleInfoClass() {
+        Class<?> clazz = this.moduleInfoClass;
+        if (clazz != null)
+            return clazz;
+
+        synchronized (this) {
+            clazz = this.moduleInfoClass;
+            if (clazz == null) {
+                if (isNamed()) {
+                    PrivilegedAction<Class<?>> pa = this::loadModuleInfoClass;
+                    clazz = AccessController.doPrivileged(pa);
+                }
+                if (clazz == null) {
+                    class DummyModuleInfo { }
+                    clazz = DummyModuleInfo.class;
+                }
+                this.moduleInfoClass = clazz;
+            }
+            return clazz;
+        }
+    }
+
+    private Class<?> loadModuleInfoClass() {
+        Class<?> clazz = null;
+        try (InputStream in = getResourceAsStream("module-info.class")) {
+            if (in != null)
+                clazz = loadModuleInfoClass(in);
+        } catch (Exception ignore) { }
+        return clazz;
+    }
+
+    /**
+     * Loads module-info.class as a package-private interface in a class loader
+     * that is a child of this module's class loader.
+     */
+    private Class<?> loadModuleInfoClass(InputStream in) throws IOException {
+        final String MODULE_INFO = "module-info";
+
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+                                         + ClassWriter.COMPUTE_FRAMES);
+
+        ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
+            @Override
+            public void visit(int version,
+                              int access,
+                              String name,
+                              String signature,
+                              String superName,
+                              String[] interfaces) {
+                cw.visit(version,
+                        Opcodes.ACC_INTERFACE
+                            + Opcodes.ACC_ABSTRACT
+                            + Opcodes.ACC_SYNTHETIC,
+                        MODULE_INFO,
+                        null,
+                        "java/lang/Object",
+                        null);
+            }
+            @Override
+            public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+                // keep annotations
+                return super.visitAnnotation(desc, visible);
+            }
+            @Override
+            public void visitAttribute(Attribute attr) {
+                // drop non-annotation attributes
+            }
+        };
+
+        ClassReader cr = new ClassReader(in);
+        cr.accept(cv, 0);
+        byte[] bytes = cw.toByteArray();
+
+        ClassLoader cl = new ClassLoader(loader) {
+            @Override
+            protected Class<?> findClass(String cn)throws ClassNotFoundException {
+                if (cn.equals(MODULE_INFO)) {
+                    return super.defineClass(cn, bytes, 0, bytes.length);
+                } else {
+                    throw new ClassNotFoundException(cn);
+                }
+            }
+        };
+
+        try {
+            return cl.loadClass(MODULE_INFO);
+        } catch (ClassNotFoundException e) {
+            throw new InternalError(e);
+        }
     }
 
 
@@ -969,16 +1378,35 @@
 
 
     /**
-     * Returns an input stream for reading a resource in this module. Returns
-     * {@code null} if the resource is not in this module or access to the
-     * resource is denied by the security manager.
-     * The {@code name} is a {@code '/'}-separated path name that identifies
-     * the resource.
+     * Returns an input stream for reading a resource in this module. The
+     * {@code name} parameter is a {@code '/'}-separated path name that
+     * identifies the resource.
      *
-     * <p> If this module is an unnamed module, and the {@code ClassLoader} for
-     * this module is not {@code null}, then this method is equivalent to
-     * invoking the {@link ClassLoader#getResourceAsStream(String)
-     * getResourceAsStream} method on the class loader for this module.
+     * <p> A resource in a named modules may be <em>encapsulated</em> so that
+     * it cannot be located by code in other modules. Whether a resource can be
+     * located or not is determined as follows:
+     *
+     * <ul>
+     *     <li> The <em>package name</em> of the resource is derived from the
+     *     subsequence of characters that precedes the last {@code '/'} and then
+     *     replacing each {@code '/'} character in the subsequence with
+     *     {@code '.'}. For example, the package name derived for a resource
+     *     named "{@code a/b/c/foo.properties}" is "{@code a.b.c}". </li>
+     *
+     *     <li> If the package name is a package in the module then the package
+     *     must be {@link #isOpen open} the module of the caller of this method.
+     *     If the package is not in the module then the resource is not
+     *     encapsulated. Resources in the unnamed package or "{@code META-INF}",
+     *     for example, are never encapsulated because they can never be
+     *     packages in a named module. </li>
+     *
+     *     <li> As a special case, resources ending with "{@code .class}" are
+     *     never encapsulated. </li>
+     * </ul>
+     *
+     * <p> This method returns {@code null} if the resource is not in this
+     * module, the resource is encapsulated and cannot be located by the caller,
+     * or access to the resource is denied by the security manager.
      *
      * @param  name
      *         The resource name
@@ -990,36 +1418,35 @@
      *
      * @see java.lang.module.ModuleReader#open(String)
      */
+    @CallerSensitive
     public InputStream getResourceAsStream(String name) throws IOException {
         Objects.requireNonNull(name);
 
-        URL url = null;
-
-        if (isNamed()) {
-            String mn = this.name;
-
-            // special-case built-in class loaders to avoid URL connection
-            if (loader == null) {
-                return BootLoader.findResourceAsStream(mn, name);
-            } else if (loader instanceof BuiltinClassLoader) {
-                return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
+        if (isNamed() && !ResourceHelper.isSimpleResource(name)) {
+            Module caller = Reflection.getCallerClass().getModule();
+            if (caller != this && caller != Object.class.getModule()) {
+                // ignore packages added for proxies via addPackage
+                Set<String> packages = getDescriptor().packages();
+                String pn = ResourceHelper.getPackageName(name);
+                if (packages.contains(pn) && !isOpen(pn, caller)) {
+                    // resource is in package not open to caller
+                    return null;
+                }
             }
-
-            // use SharedSecrets to invoke protected method
-            url = SharedSecrets.getJavaLangAccess().findResource(loader, mn, name);
-
-        } else {
-
-            // unnamed module
-            if (loader == null) {
-                url = BootLoader.findResource(name);
-            } else {
-                return loader.getResourceAsStream(name);
-            }
-
         }
 
-        // fallthrough to URL case
+        String mn = this.name;
+
+        // special-case built-in class loaders to avoid URL connection
+        if (loader == null) {
+            return BootLoader.findResourceAsStream(mn, name);
+        } else if (loader instanceof BuiltinClassLoader) {
+            return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
+        }
+
+        // locate resource in module
+        JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
+        URL url = jla.findResource(loader, mn, name);
         if (url != null) {
             try {
                 return url.openStream();
@@ -1053,6 +1480,7 @@
 
     // JVM_DefineModule
     private static native void defineModule0(Module module,
+                                             boolean isOpen,
                                              String version,
                                              String location,
                                              String[] pns);
@@ -1098,15 +1526,31 @@
                 }
                 @Override
                 public void addExports(Module m, String pn, Module other) {
-                    m.implAddExports(pn, other, true);
+                    m.implAddExportsOrOpens(pn, other, false, true);
+                }
+                @Override
+                public void addOpens(Module m, String pn, Module other) {
+                    m.implAddExportsOrOpens(pn, other, true, true);
                 }
                 @Override
                 public void addExportsToAll(Module m, String pn) {
-                    m.implAddExports(pn, Module.EVERYONE_MODULE, true);
+                    m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
+                }
+                @Override
+                public void addOpensToAll(Module m, String pn) {
+                    m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true);
                 }
                 @Override
                 public void addExportsToAllUnnamed(Module m, String pn) {
-                    m.implAddExports(pn, Module.ALL_UNNAMED_MODULE, true);
+                    m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
+                }
+                @Override
+                public void addOpensToAllUnnamed(Module m, String pn) {
+                    m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
+                }
+                @Override
+                public void addUses(Module m, Class<?> service) {
+                    m.implAddUses(service);
                 }
                 @Override
                 public void addPackage(Module m, String pn) {
@@ -1116,6 +1560,14 @@
                 public ServicesCatalog getServicesCatalog(Layer layer) {
                     return layer.getServicesCatalog();
                 }
+                @Override
+                public Stream<Layer> layers(Layer layer) {
+                    return layer.layers();
+                }
+                @Override
+                public Stream<Layer> layers(ClassLoader loader) {
+                    return Layer.layers(loader);
+                }
             });
     }
 }
diff --git a/jdk/src/java.base/share/classes/java/net/Authenticator.java b/jdk/src/java.base/share/classes/java/net/Authenticator.java
index 81a87c7..16af284 100644
--- a/jdk/src/java.base/share/classes/java/net/Authenticator.java
+++ b/jdk/src/java.base/share/classes/java/net/Authenticator.java
@@ -25,6 +25,8 @@
 
 package java.net;
 
+import sun.net.www.protocol.http.AuthenticatorKeys;
+
 /**
  * The class Authenticator represents an object that knows how to obtain
  * authentication for a network connection.  Usually, it will do this
@@ -70,6 +72,7 @@
     private String requestingScheme;
     private URL requestingURL;
     private RequestorType requestingAuthType;
+    private final String key = AuthenticatorKeys.computeKey(this);
 
     /**
      * The type of the entity requesting authentication.
@@ -349,6 +352,75 @@
     }
 
     /**
+     * Ask the given {@code authenticator} for a password. If the given
+     * {@code authenticator} is null, the authenticator, if any, that has been
+     * registered with the system using {@link #setDefault(java.net.Authenticator)
+     * setDefault} is used.
+     * <p>
+     * First, if there is a security manager, its {@code checkPermission}
+     * method is called with a
+     * {@code NetPermission("requestPasswordAuthentication")} permission.
+     * This may result in a java.lang.SecurityException.
+     *
+     * @param authenticator the authenticator, or {@code null}.
+     * @param host The hostname of the site requesting authentication.
+     * @param addr The InetAddress of the site requesting authorization,
+     *             or null if not known.
+     * @param port the port for the requested connection
+     * @param protocol The protocol that's requesting the connection
+     *          ({@link java.net.Authenticator#getRequestingProtocol()})
+     * @param prompt A prompt string for the user
+     * @param scheme The authentication scheme
+     * @param url The requesting URL that caused the authentication
+     * @param reqType The type (server or proxy) of the entity requesting
+     *              authentication.
+     *
+     * @return The username/password, or {@code null} if one can't be gotten.
+     *
+     * @throws SecurityException
+     *        if a security manager exists and its
+     *        {@code checkPermission} method doesn't allow
+     *        the password authentication request.
+     *
+     * @see SecurityManager#checkPermission
+     * @see java.net.NetPermission
+     *
+     * @since 9
+     */
+    public static PasswordAuthentication requestPasswordAuthentication(
+                                    Authenticator authenticator,
+                                    String host,
+                                    InetAddress addr,
+                                    int port,
+                                    String protocol,
+                                    String prompt,
+                                    String scheme,
+                                    URL url,
+                                    RequestorType reqType) {
+
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            NetPermission requestPermission
+                = new NetPermission("requestPasswordAuthentication");
+            sm.checkPermission(requestPermission);
+        }
+
+        Authenticator a = authenticator == null ? theAuthenticator : authenticator;
+        if (a == null) {
+            return null;
+        } else {
+            return a.requestPasswordAuthenticationInstance(host,
+                                                           addr,
+                                                           port,
+                                                           protocol,
+                                                           prompt,
+                                                           scheme,
+                                                           url,
+                                                           reqType);
+        }
+    }
+
+    /**
      * Ask this authenticator for a password.
      *
      * @param host The hostname of the site requesting authentication.
@@ -493,4 +565,11 @@
     protected RequestorType getRequestorType () {
         return requestingAuthType;
     }
+
+    static String getKey(Authenticator a) {
+        return a.key;
+    }
+    static {
+        AuthenticatorKeys.setAuthenticatorKeyAccess(Authenticator::getKey);
+    }
 }
diff --git a/jdk/src/java.base/share/classes/java/net/HttpURLConnection.java b/jdk/src/java.base/share/classes/java/net/HttpURLConnection.java
index 94b537d..9e428e5 100644
--- a/jdk/src/java.base/share/classes/java/net/HttpURLConnection.java
+++ b/jdk/src/java.base/share/classes/java/net/HttpURLConnection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,53 @@
     protected long fixedContentLengthLong = -1;
 
     /**
+     * Supplies an {@link java.net.Authenticator Authenticator} to be used
+     * when authentication is requested through the HTTP protocol for
+     * this {@code HttpURLConnection}.
+     * If no authenticator is supplied, the
+     * {@linkplain Authenticator#setDefault(java.net.Authenticator) default
+     * authenticator} will be used.
+     *
+     * @implSpec The default behavior of this method is to unconditionally
+     *           throw {@link UnsupportedOperationException}. Concrete
+     *           implementations of {@code HttpURLConnection}
+     *           which support supplying an {@code Authenticator} for a
+     *           specific {@code HttpURLConnection} instance should
+     *           override this method to implement a different behavior.
+     *
+     * @implNote Depending on authentication schemes, an implementation
+     *           may or may not need to use the provided authenticator
+     *           to obtain a password. For instance, an implementation that
+     *           relies on third-party security libraries may still invoke the
+     *           default authenticator if these libraries are configured
+     *           to do so.
+     *           Likewise, an implementation that supports transparent
+     *           NTLM authentication may let the system attempt
+     *           to connect using the system user credentials first,
+     *           before invoking the provided authenticator.
+     *           <br>
+     *           However, if an authenticator is specifically provided,
+     *           then the underlying connection may only be reused for
+     *           {@code HttpURLConnection} instances which share the same
+     *           {@code Authenticator} instance, and authentication information,
+     *           if cached, may only be reused for an {@code HttpURLConnection}
+     *           sharing that same {@code Authenticator}.
+     *
+     * @param auth The {@code Authenticator} that should be used by this
+     *           {@code HttpURLConnection}.
+     *
+     * @throws  UnsupportedOperationException if setting an Authenticator is
+     *          not supported by the underlying implementation.
+     * @throws  IllegalStateException if URLConnection is already connected.
+     * @throws  NullPointerException if the supplied {@code auth} is {@code null}.
+     * @since 9
+     */
+    public void setAuthenticator(Authenticator auth) {
+        throw new UnsupportedOperationException("Supplying an authenticator"
+                    + " is not supported by " + this.getClass());
+    }
+
+    /**
      * Returns the key for the {@code n}<sup>th</sup> header field.
      * Some implementations may treat the {@code 0}<sup>th</sup>
      * header field as special, i.e. as the status line returned by the HTTP
diff --git a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
index 602f9d7..57f4502 100644
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
@@ -72,6 +72,10 @@
  * <p>
  * The classes that are loaded are by default granted permission only to
  * access the URLs specified when the URLClassLoader was created.
+ * <p>
+ * This class loader supports the loading of classes from the contents of a
+ * <a href="../util/jar/JarFile.html#multirelease">multi-release</a> JAR file
+ * that is referred to by a given URL.
  *
  * @author  David Connelly
  * @since   1.2
diff --git a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java
index c9d6baa..d1c3919 100644
--- a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java
+++ b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java
@@ -151,7 +151,7 @@
  * Each chronology must define a chronology ID that is unique within the system.
  * If the chronology represents a calendar system defined by the
  * CLDR specification then the calendar type is the concatenation of the
- * CLDR type and, if applicable, the CLDR variant,
+ * CLDR type and, if applicable, the CLDR variant.
  *
  * @implSpec
  * This interface must be implemented with care to ensure other classes operate correctly.
@@ -177,7 +177,7 @@
      *
      * @param temporal  the temporal to convert, not null
      * @return the chronology, not null
-     * @throws DateTimeException if unable to convert to an {@code Chronology}
+     * @throws DateTimeException if unable to convert to a {@code Chronology}
      */
     static Chronology from(TemporalAccessor temporal) {
         Objects.requireNonNull(temporal, "temporal");
@@ -203,7 +203,7 @@
      * For example, the locale "en-JP-u-ca-japanese" represents the English
      * language as used in Japan with the Japanese calendar system.
      * <p>
-     * This method finds the desired calendar system by in a manner equivalent
+     * This method finds the desired calendar system in a manner equivalent
      * to passing "ca" to {@link Locale#getUnicodeLocaleType(String)}.
      * If the "ca" key is not present, then {@code IsoChronology} is returned.
      * <p>
@@ -286,7 +286,7 @@
      * <p>
      * The calendar type is an identifier defined by the CLDR and
      * <em>Unicode Locale Data Markup Language (LDML)</em> specifications
-     * to uniquely identification a calendar.
+     * to uniquely identify a calendar.
      * The {@code getCalendarType} is the concatenation of the CLDR calendar type
      * and the variant, if applicable, is appended separated by "-".
      * The calendar type is used to lookup the {@code Chronology} using {@link #of(String)}.
diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
index 9beb695..0e6eb06 100644
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -119,6 +119,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.locale.provider.LocaleProviderAdapter;
 import sun.util.locale.provider.LocaleResources;
 import sun.util.locale.provider.TimeZoneNameUtility;
@@ -212,9 +213,10 @@
         if (dateStyle == null && timeStyle == null) {
             throw new IllegalArgumentException("Either dateStyle or timeStyle must be non-null");
         }
-        LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale);
-        String pattern = lr.getJavaTimeDateTimePattern(
-                convertStyle(timeStyle), convertStyle(dateStyle), chrono.getCalendarType());
+        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, locale);
+        JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider();
+        String pattern = provider.getJavaTimeDateTimePattern(convertStyle(timeStyle),
+                         convertStyle(dateStyle), chrono.getCalendarType(), locale);
         return pattern;
     }
 
diff --git a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java
index 5a9b831..0122f9e 100644
--- a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java
+++ b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java
@@ -36,6 +36,8 @@
 
 import java.io.Serializable;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
 
 /**
  * Resizable-array implementation of the {@link Deque} interface.  Array
@@ -87,81 +89,89 @@
 public class ArrayDeque<E> extends AbstractCollection<E>
                            implements Deque<E>, Cloneable, Serializable
 {
+    /*
+     * VMs excel at optimizing simple array loops where indices are
+     * incrementing or decrementing over a valid slice, e.g.
+     *
+     * for (int i = start; i < end; i++) ... elements[i]
+     *
+     * Because in a circular array, elements are in general stored in
+     * two disjoint such slices, we help the VM by writing unusual
+     * nested loops for all traversals over the elements.  Having only
+     * one hot inner loop body instead of two or three eases human
+     * maintenance and encourages VM loop inlining into the caller.
+     */
+
     /**
      * The array in which the elements of the deque are stored.
-     * The capacity of the deque is the length of this array, which is
-     * always a power of two. The array is never allowed to become
-     * full, except transiently within an addX method where it is
-     * resized (see doubleCapacity) immediately upon becoming full,
-     * thus avoiding head and tail wrapping around to equal each
-     * other.  We also guarantee that all array cells not holding
-     * deque elements are always null.
+     * All array cells not holding deque elements are always null.
+     * The array always has at least one null slot (at tail).
      */
-    transient Object[] elements; // non-private to simplify nested class access
+    transient Object[] elements;
 
     /**
      * The index of the element at the head of the deque (which is the
      * element that would be removed by remove() or pop()); or an
-     * arbitrary number equal to tail if the deque is empty.
+     * arbitrary number 0 <= head < elements.length equal to tail if
+     * the deque is empty.
      */
     transient int head;
 
     /**
      * The index at which the next element would be added to the tail
-     * of the deque (via addLast(E), add(E), or push(E)).
+     * of the deque (via addLast(E), add(E), or push(E));
+     * elements[tail] is always null.
      */
     transient int tail;
 
     /**
-     * The minimum capacity that we'll use for a newly created deque.
-     * Must be a power of 2.
+     * The maximum size of array to allocate.
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
      */
-    private static final int MIN_INITIAL_CAPACITY = 8;
-
-    // ******  Array allocation and resizing utilities ******
+    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 
     /**
-     * Allocates empty array to hold the given number of elements.
+     * Increases the capacity of this deque by at least the given amount.
      *
-     * @param numElements  the number of elements to hold
+     * @param needed the required minimum extra capacity; must be positive
      */
-    private void allocateElements(int numElements) {
-        int initialCapacity = MIN_INITIAL_CAPACITY;
-        // Find the best power of two to hold elements.
-        // Tests "<=" because arrays aren't kept full.
-        if (numElements >= initialCapacity) {
-            initialCapacity = numElements;
-            initialCapacity |= (initialCapacity >>>  1);
-            initialCapacity |= (initialCapacity >>>  2);
-            initialCapacity |= (initialCapacity >>>  4);
-            initialCapacity |= (initialCapacity >>>  8);
-            initialCapacity |= (initialCapacity >>> 16);
-            initialCapacity++;
-
-            if (initialCapacity < 0)    // Too many elements, must back off
-                initialCapacity >>>= 1; // Good luck allocating 2^30 elements
+    private void grow(int needed) {
+        // overflow-conscious code
+        final int oldCapacity = elements.length;
+        int newCapacity;
+        // Double capacity if small; else grow by 50%
+        int jump = (oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1);
+        if (jump < needed
+            || (newCapacity = (oldCapacity + jump)) - MAX_ARRAY_SIZE > 0)
+            newCapacity = newCapacity(needed, jump);
+        elements = Arrays.copyOf(elements, newCapacity);
+        // Exceptionally, here tail == head needs to be disambiguated
+        if (tail < head || (tail == head && elements[head] != null)) {
+            // wrap around; slide first leg forward to end of array
+            int newSpace = newCapacity - oldCapacity;
+            System.arraycopy(elements, head,
+                             elements, head + newSpace,
+                             oldCapacity - head);
+            Arrays.fill(elements, head, head + newSpace, null);
+            head += newSpace;
         }
-        elements = new Object[initialCapacity];
     }
 
-    /**
-     * Doubles the capacity of this deque.  Call only when full, i.e.,
-     * when head and tail have wrapped around to become equal.
-     */
-    private void doubleCapacity() {
-        assert head == tail;
-        int p = head;
-        int n = elements.length;
-        int r = n - p; // number of elements to the right of p
-        int newCapacity = n << 1;
-        if (newCapacity < 0)
-            throw new IllegalStateException("Sorry, deque too big");
-        Object[] a = new Object[newCapacity];
-        System.arraycopy(elements, p, a, 0, r);
-        System.arraycopy(elements, 0, a, r, p);
-        elements = a;
-        head = 0;
-        tail = n;
+    /** Capacity calculation for edge conditions, especially overflow. */
+    private int newCapacity(int needed, int jump) {
+        final int oldCapacity = elements.length, minCapacity;
+        if ((minCapacity = oldCapacity + needed) - MAX_ARRAY_SIZE > 0) {
+            if (minCapacity < 0)
+                throw new IllegalStateException("Sorry, deque too big");
+            return Integer.MAX_VALUE;
+        }
+        if (needed > jump)
+            return minCapacity;
+        return (oldCapacity + jump - MAX_ARRAY_SIZE < 0)
+            ? oldCapacity + jump
+            : MAX_ARRAY_SIZE;
     }
 
     /**
@@ -176,10 +186,13 @@
      * Constructs an empty array deque with an initial capacity
      * sufficient to hold the specified number of elements.
      *
-     * @param numElements  lower bound on initial capacity of the deque
+     * @param numElements lower bound on initial capacity of the deque
      */
     public ArrayDeque(int numElements) {
-        allocateElements(numElements);
+        elements =
+            new Object[(numElements < 1) ? 1 :
+                       (numElements == Integer.MAX_VALUE) ? Integer.MAX_VALUE :
+                       numElements + 1];
     }
 
     /**
@@ -193,10 +206,71 @@
      * @throws NullPointerException if the specified collection is null
      */
     public ArrayDeque(Collection<? extends E> c) {
-        allocateElements(c.size());
+        this(c.size());
         addAll(c);
     }
 
+    /**
+     * Increments i, mod modulus.
+     * Precondition and postcondition: 0 <= i < modulus.
+     */
+    static final int inc(int i, int modulus) {
+        if (++i >= modulus) i = 0;
+        return i;
+    }
+
+    /**
+     * Decrements i, mod modulus.
+     * Precondition and postcondition: 0 <= i < modulus.
+     */
+    static final int dec(int i, int modulus) {
+        if (--i < 0) i = modulus - 1;
+        return i;
+    }
+
+    /**
+     * Circularly adds the given distance to index i, mod modulus.
+     * Precondition: 0 <= i < modulus, 0 <= distance <= modulus.
+     * @return index 0 <= i < modulus
+     */
+    static final int add(int i, int distance, int modulus) {
+        if ((i += distance) - modulus >= 0) i -= modulus;
+        return i;
+    }
+
+    /**
+     * Subtracts j from i, mod modulus.
+     * Index i must be logically ahead of index j.
+     * Precondition: 0 <= i < modulus, 0 <= j < modulus.
+     * @return the "circular distance" from j to i; corner case i == j
+     * is diambiguated to "empty", returning 0.
+     */
+    static final int sub(int i, int j, int modulus) {
+        if ((i -= j) < 0) i += modulus;
+        return i;
+    }
+
+    /**
+     * Returns element at array index i.
+     * This is a slight abuse of generics, accepted by javac.
+     */
+    @SuppressWarnings("unchecked")
+    static final <E> E elementAt(Object[] es, int i) {
+        return (E) es[i];
+    }
+
+    /**
+     * A version of elementAt that checks for null elements.
+     * This check doesn't catch all possible comodifications,
+     * but does catch ones that corrupt traversal.
+     */
+    static final <E> E nonNullElementAt(Object[] es, int i) {
+        @SuppressWarnings("unchecked") E e = (E) es[i];
+        if (e == null)
+            throw new ConcurrentModificationException();
+        return e;
+    }
+
     // The main insertion and extraction methods are addFirst,
     // addLast, pollFirst, pollLast. The other methods are defined in
     // terms of these.
@@ -210,9 +284,10 @@
     public void addFirst(E e) {
         if (e == null)
             throw new NullPointerException();
-        elements[head = (head - 1) & (elements.length - 1)] = e;
+        final Object[] es = elements;
+        es[head = dec(head, es.length)] = e;
         if (head == tail)
-            doubleCapacity();
+            grow(1);
     }
 
     /**
@@ -226,9 +301,29 @@
     public void addLast(E e) {
         if (e == null)
             throw new NullPointerException();
-        elements[tail] = e;
-        if ( (tail = (tail + 1) & (elements.length - 1)) == head)
-            doubleCapacity();
+        final Object[] es = elements;
+        es[tail] = e;
+        if (head == (tail = inc(tail, es.length)))
+            grow(1);
+    }
+
+    /**
+     * Adds all of the elements in the specified collection at the end
+     * of this deque, as if by calling {@link #addLast} on each one,
+     * in the order that they are returned by the collection's
+     * iterator.
+     *
+     * @param c the elements to be inserted into this deque
+     * @return {@code true} if this deque changed as a result of the call
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        final int s, needed;
+        if ((needed = (s = size()) + c.size() + 1 - elements.length) > 0)
+            grow(needed);
+        c.forEach(this::addLast);
+        return size() > s;
     }
 
     /**
@@ -259,78 +354,70 @@
      * @throws NoSuchElementException {@inheritDoc}
      */
     public E removeFirst() {
-        E x = pollFirst();
-        if (x == null)
+        E e = pollFirst();
+        if (e == null)
             throw new NoSuchElementException();
-        return x;
+        return e;
     }
 
     /**
      * @throws NoSuchElementException {@inheritDoc}
      */
     public E removeLast() {
-        E x = pollLast();
-        if (x == null)
+        E e = pollLast();
+        if (e == null)
             throw new NoSuchElementException();
-        return x;
+        return e;
     }
 
     public E pollFirst() {
-        final Object[] elements = this.elements;
-        final int h = head;
-        @SuppressWarnings("unchecked")
-        E result = (E) elements[h];
-        // Element is null if deque empty
-        if (result != null) {
-            elements[h] = null; // Must null out slot
-            head = (h + 1) & (elements.length - 1);
+        final Object[] es;
+        final int h;
+        E e = elementAt(es = elements, h = head);
+        if (e != null) {
+            es[h] = null;
+            head = inc(h, es.length);
         }
-        return result;
+        return e;
     }
 
     public E pollLast() {
-        final Object[] elements = this.elements;
-        final int t = (tail - 1) & (elements.length - 1);
-        @SuppressWarnings("unchecked")
-        E result = (E) elements[t];
-        if (result != null) {
-            elements[t] = null;
-            tail = t;
-        }
-        return result;
+        final Object[] es;
+        final int t;
+        E e = elementAt(es = elements, t = dec(tail, es.length));
+        if (e != null)
+            es[tail = t] = null;
+        return e;
     }
 
     /**
      * @throws NoSuchElementException {@inheritDoc}
      */
     public E getFirst() {
-        @SuppressWarnings("unchecked")
-        E result = (E) elements[head];
-        if (result == null)
+        E e = elementAt(elements, head);
+        if (e == null)
             throw new NoSuchElementException();
-        return result;
+        return e;
     }
 
     /**
      * @throws NoSuchElementException {@inheritDoc}
      */
     public E getLast() {
-        @SuppressWarnings("unchecked")
-        E result = (E) elements[(tail - 1) & (elements.length - 1)];
-        if (result == null)
+        final Object[] es = elements;
+        E e = elementAt(es, dec(tail, es.length));
+        if (e == null)
             throw new NoSuchElementException();
-        return result;
+        return e;
     }
 
-    @SuppressWarnings("unchecked")
     public E peekFirst() {
-        // elements[head] is null if deque empty
-        return (E) elements[head];
+        return elementAt(elements, head);
     }
 
-    @SuppressWarnings("unchecked")
     public E peekLast() {
-        return (E) elements[(tail - 1) & (elements.length - 1)];
+        final Object[] es;
+        return elementAt(es = elements, dec(tail, es.length));
     }
 
     /**
@@ -347,13 +434,15 @@
      */
     public boolean removeFirstOccurrence(Object o) {
         if (o != null) {
-            int mask = elements.length - 1;
-            int i = head;
-            for (Object x; (x = elements[i]) != null; i = (i + 1) & mask) {
-                if (o.equals(x)) {
-                    delete(i);
-                    return true;
-                }
+            final Object[] es = elements;
+            for (int i = head, end = tail, to = (i <= end) ? end : es.length;
+                 ; i = 0, to = end) {
+                for (; i < to; i++)
+                    if (o.equals(es[i])) {
+                        delete(i);
+                        return true;
+                    }
+                if (to == end) break;
             }
         }
         return false;
@@ -373,13 +462,15 @@
      */
     public boolean removeLastOccurrence(Object o) {
         if (o != null) {
-            int mask = elements.length - 1;
-            int i = (tail - 1) & mask;
-            for (Object x; (x = elements[i]) != null; i = (i - 1) & mask) {
-                if (o.equals(x)) {
-                    delete(i);
-                    return true;
-                }
+            final Object[] es = elements;
+            for (int i = tail, end = head, to = (i >= end) ? end : 0;
+                 ; i = es.length, to = end) {
+                for (i--; i > to - 1; i--)
+                    if (o.equals(es[i])) {
+                        delete(i);
+                        return true;
+                    }
+                if (to == end) break;
             }
         }
         return false;
@@ -499,59 +590,47 @@
         return removeFirst();
     }
 
-    private void checkInvariants() {
-        assert elements[tail] == null;
-        assert head == tail ? elements[head] == null :
-            (elements[head] != null &&
-             elements[(tail - 1) & (elements.length - 1)] != null);
-        assert elements[(head - 1) & (elements.length - 1)] == null;
-    }
-
     /**
-     * Removes the element at the specified position in the elements array,
-     * adjusting head and tail as necessary.  This can result in motion of
-     * elements backwards or forwards in the array.
+     * Removes the element at the specified position in the elements array.
+     * This can result in forward or backwards motion of array elements.
+     * We optimize for least element motion.
      *
      * <p>This method is called delete rather than remove to emphasize
      * that its semantics differ from those of {@link List#remove(int)}.
      *
-     * @return true if elements moved backwards
+     * @return true if elements near tail moved backwards
      */
     boolean delete(int i) {
-        checkInvariants();
-        final Object[] elements = this.elements;
-        final int mask = elements.length - 1;
-        final int h = head;
-        final int t = tail;
-        final int front = (i - h) & mask;
-        final int back  = (t - i) & mask;
-
-        // Invariant: head <= i < tail mod circularity
-        if (front >= ((t - h) & mask))
-            throw new ConcurrentModificationException();
-
-        // Optimize for least element motion
+        final Object[] es = elements;
+        final int capacity = es.length;
+        final int h, t;
+        // number of elements before to-be-deleted elt
+        final int front = sub(i, h = head, capacity);
+        // number of elements after to-be-deleted elt
+        final int back = sub(t = tail, i, capacity) - 1;
         if (front < back) {
+            // move front elements forwards
             if (h <= i) {
-                System.arraycopy(elements, h, elements, h + 1, front);
+                System.arraycopy(es, h, es, h + 1, front);
             } else { // Wrap around
-                System.arraycopy(elements, 0, elements, 1, i);
-                elements[0] = elements[mask];
-                System.arraycopy(elements, h, elements, h + 1, mask - h);
+                System.arraycopy(es, 0, es, 1, i);
+                es[0] = es[capacity - 1];
+                System.arraycopy(es, h, es, h + 1, front - (i + 1));
             }
-            elements[h] = null;
-            head = (h + 1) & mask;
+            es[h] = null;
+            head = inc(h, capacity);
             return false;
         } else {
-            if (i < t) { // Copy the null tail as well
-                System.arraycopy(elements, i + 1, elements, i, back);
-                tail = t - 1;
+            // move back elements backwards
+            tail = dec(t, capacity);
+            if (i <= tail) {
+                System.arraycopy(es, i + 1, es, i, back);
             } else { // Wrap around
-                System.arraycopy(elements, i + 1, elements, i, mask - i);
-                elements[mask] = elements[0];
-                System.arraycopy(elements, 1, elements, 0, t);
-                tail = (t - 1) & mask;
+                System.arraycopy(es, i + 1, es, i, capacity - (i + 1));
+                es[capacity - 1] = es[0];
+                System.arraycopy(es, 1, es, 0, t - 1);
             }
+            es[tail] = null;
             return true;
         }
     }
@@ -564,7 +643,7 @@
      * @return the number of elements in this deque
      */
     public int size() {
-        return (tail - head) & (elements.length - 1);
+        return sub(tail, head, elements.length);
     }
 
     /**
@@ -593,101 +672,317 @@
     }
 
     private class DeqIterator implements Iterator<E> {
-        /**
-         * Index of element to be returned by subsequent call to next.
-         */
-        private int cursor = head;
+        /** Index of element to be returned by subsequent call to next. */
+        int cursor;
 
-        /**
-         * Tail recorded at construction (also in remove), to stop
-         * iterator and also to check for comodification.
-         */
-        private int fence = tail;
+        /** Number of elements yet to be returned. */
+        int remaining = size();
 
         /**
          * Index of element returned by most recent call to next.
          * Reset to -1 if element is deleted by a call to remove.
          */
-        private int lastRet = -1;
+        int lastRet = -1;
 
-        public boolean hasNext() {
-            return cursor != fence;
+        DeqIterator() { cursor = head; }
+
+        public final boolean hasNext() {
+            return remaining > 0;
         }
 
         public E next() {
-            if (cursor == fence)
+            if (remaining <= 0)
                 throw new NoSuchElementException();
-            @SuppressWarnings("unchecked")
-            E result = (E) elements[cursor];
-            // This check doesn't catch all possible comodifications,
-            // but does catch the ones that corrupt traversal
-            if (tail != fence || result == null)
-                throw new ConcurrentModificationException();
-            lastRet = cursor;
-            cursor = (cursor + 1) & (elements.length - 1);
-            return result;
+            final Object[] es = elements;
+            E e = nonNullElementAt(es, cursor);
+            cursor = inc(lastRet = cursor, es.length);
+            remaining--;
+            return e;
         }
 
-        public void remove() {
+        void postDelete(boolean leftShifted) {
+            if (leftShifted)
+                cursor = dec(cursor, elements.length);
+        }
+
+        public final void remove() {
             if (lastRet < 0)
                 throw new IllegalStateException();
-            if (delete(lastRet)) { // if left-shifted, undo increment in next()
-                cursor = (cursor - 1) & (elements.length - 1);
-                fence = tail;
-            }
+            postDelete(delete(lastRet));
             lastRet = -1;
         }
 
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
-            Object[] a = elements;
-            int m = a.length - 1, f = fence, i = cursor;
-            cursor = f;
-            while (i != f) {
-                @SuppressWarnings("unchecked") E e = (E)a[i];
-                i = (i + 1) & m;
-                if (e == null)
-                    throw new ConcurrentModificationException();
-                action.accept(e);
+            int r;
+            if ((r = remaining) <= 0)
+                return;
+            remaining = 0;
+            final Object[] es = elements;
+            if (es[cursor] == null || sub(tail, cursor, es.length) != r)
+                throw new ConcurrentModificationException();
+            for (int i = cursor, end = tail, to = (i <= end) ? end : es.length;
+                 ; i = 0, to = end) {
+                for (; i < to; i++)
+                    action.accept(elementAt(es, i));
+                if (to == end) {
+                    if (end != tail)
+                        throw new ConcurrentModificationException();
+                    lastRet = dec(end, es.length);
+                    break;
+                }
+            }
+        }
+    }
+
+    private class DescendingIterator extends DeqIterator {
+        DescendingIterator() { cursor = dec(tail, elements.length); }
+
+        public final E next() {
+            if (remaining <= 0)
+                throw new NoSuchElementException();
+            final Object[] es = elements;
+            E e = nonNullElementAt(es, cursor);
+            cursor = dec(lastRet = cursor, es.length);
+            remaining--;
+            return e;
+        }
+
+        void postDelete(boolean leftShifted) {
+            if (!leftShifted)
+                cursor = inc(cursor, elements.length);
+        }
+
+        public final void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            int r;
+            if ((r = remaining) <= 0)
+                return;
+            remaining = 0;
+            final Object[] es = elements;
+            if (es[cursor] == null || sub(cursor, head, es.length) + 1 != r)
+                throw new ConcurrentModificationException();
+            for (int i = cursor, end = head, to = (i >= end) ? end : 0;
+                 ; i = es.length - 1, to = end) {
+                // hotspot generates faster code than for: i >= to !
+                for (; i > to - 1; i--)
+                    action.accept(elementAt(es, i));
+                if (to == end) {
+                    if (end != head)
+                        throw new ConcurrentModificationException();
+                    lastRet = end;
+                    break;
+                }
             }
         }
     }
 
     /**
-     * This class is nearly a mirror-image of DeqIterator, using tail
-     * instead of head for initial cursor, and head instead of tail
-     * for fence.
+     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
+     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
+     * deque.
+     *
+     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
+     * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
+     * {@link Spliterator#NONNULL}.  Overriding implementations should document
+     * the reporting of additional characteristic values.
+     *
+     * @return a {@code Spliterator} over the elements in this deque
+     * @since 1.8
      */
-    private class DescendingIterator implements Iterator<E> {
-        private int cursor = tail;
-        private int fence = head;
-        private int lastRet = -1;
+    public Spliterator<E> spliterator() {
+        return new DeqSpliterator();
+    }
 
-        public boolean hasNext() {
-            return cursor != fence;
+    final class DeqSpliterator implements Spliterator<E> {
+        private int fence;      // -1 until first use
+        private int cursor;     // current index, modified on traverse/split
+
+        /** Constructs late-binding spliterator over all elements. */
+        DeqSpliterator() {
+            this.fence = -1;
         }
 
-        public E next() {
-            if (cursor == fence)
-                throw new NoSuchElementException();
-            cursor = (cursor - 1) & (elements.length - 1);
-            @SuppressWarnings("unchecked")
-            E result = (E) elements[cursor];
-            if (head != fence || result == null)
-                throw new ConcurrentModificationException();
-            lastRet = cursor;
-            return result;
+        /** Constructs spliterator over the given range. */
+        DeqSpliterator(int origin, int fence) {
+            // assert 0 <= origin && origin < elements.length;
+            // assert 0 <= fence && fence < elements.length;
+            this.cursor = origin;
+            this.fence = fence;
         }
 
-        public void remove() {
-            if (lastRet < 0)
-                throw new IllegalStateException();
-            if (!delete(lastRet)) {
-                cursor = (cursor + 1) & (elements.length - 1);
-                fence = head;
+        /** Ensures late-binding initialization; then returns fence. */
+        private int getFence() { // force initialization
+            int t;
+            if ((t = fence) < 0) {
+                t = fence = tail;
+                cursor = head;
             }
-            lastRet = -1;
+            return t;
         }
+
+        public DeqSpliterator trySplit() {
+            final Object[] es = elements;
+            final int i, n;
+            return ((n = sub(getFence(), i = cursor, es.length) >> 1) <= 0)
+                ? null
+                : new DeqSpliterator(i, cursor = add(i, n, es.length));
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            if (action == null)
+                throw new NullPointerException();
+            final int end = getFence(), cursor = this.cursor;
+            final Object[] es = elements;
+            if (cursor != end) {
+                this.cursor = end;
+                // null check at both ends of range is sufficient
+                if (es[cursor] == null || es[dec(end, es.length)] == null)
+                    throw new ConcurrentModificationException();
+                for (int i = cursor, to = (i <= end) ? end : es.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        action.accept(elementAt(es, i));
+                    if (to == end) break;
+                }
+            }
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            final Object[] es = elements;
+            if (fence < 0) { fence = tail; cursor = head; } // late-binding
+            final int i;
+            if ((i = cursor) == fence)
+                return false;
+            E e = nonNullElementAt(es, i);
+            cursor = inc(i, es.length);
+            action.accept(e);
+            return true;
+        }
+
+        public long estimateSize() {
+            return sub(getFence(), cursor, elements.length);
+        }
+
+        public int characteristics() {
+            return Spliterator.NONNULL
+                | Spliterator.ORDERED
+                | Spliterator.SIZED
+                | Spliterator.SUBSIZED;
+        }
+    }
+
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        final Object[] es = elements;
+        for (int i = head, end = tail, to = (i <= end) ? end : es.length;
+             ; i = 0, to = end) {
+            for (; i < to; i++)
+                action.accept(elementAt(es, i));
+            if (to == end) {
+                if (end != tail) throw new ConcurrentModificationException();
+                break;
+            }
+        }
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    /** Implementation of bulk remove methods. */
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        final Object[] es = elements;
+        // Optimize for initial run of survivors
+        for (int i = head, end = tail, to = (i <= end) ? end : es.length;
+             ; i = 0, to = end) {
+            for (; i < to; i++)
+                if (filter.test(elementAt(es, i)))
+                    return bulkRemoveModified(filter, i);
+            if (to == end) {
+                if (end != tail) throw new ConcurrentModificationException();
+                break;
+            }
+        }
+        return false;
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    /**
+     * Helper for bulkRemove, in case of at least one deletion.
+     * Tolerate predicates that reentrantly access the collection for
+     * read (but writers still get CME), so traverse once to find
+     * elements to delete, a second pass to physically expunge.
+     *
+     * @param beg valid index of first element to be deleted
+     */
+    private boolean bulkRemoveModified(
+        Predicate<? super E> filter, final int beg) {
+        final Object[] es = elements;
+        final int capacity = es.length;
+        final int end = tail;
+        final long[] deathRow = nBits(sub(end, beg, capacity));
+        deathRow[0] = 1L;   // set bit 0
+        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
+             ; i = 0, to = end, k -= capacity) {
+            for (; i < to; i++)
+                if (filter.test(elementAt(es, i)))
+                    setBit(deathRow, i - k);
+            if (to == end) break;
+        }
+        // a two-finger traversal, with hare i reading, tortoise w writing
+        int w = beg;
+        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
+             ; w = 0) { // w rejoins i on second leg
+            // In this loop, i and w are on the same leg, with i > w
+            for (; i < to; i++)
+                if (isClear(deathRow, i - k))
+                    es[w++] = es[i];
+            if (to == end) break;
+            // In this loop, w is on the first leg, i on the second
+            for (i = 0, to = end, k -= capacity; i < to && w < capacity; i++)
+                if (isClear(deathRow, i - k))
+                    es[w++] = es[i];
+            if (i >= to) {
+                if (w == capacity) w = 0; // "corner" case
+                break;
+            }
+        }
+        if (end != tail) throw new ConcurrentModificationException();
+        circularClear(es, tail = w, end);
+        return true;
     }
 
     /**
@@ -700,11 +995,13 @@
      */
     public boolean contains(Object o) {
         if (o != null) {
-            int mask = elements.length - 1;
-            int i = head;
-            for (Object x; (x = elements[i]) != null; i = (i + 1) & mask) {
-                if (o.equals(x))
-                    return true;
+            final Object[] es = elements;
+            for (int i = head, end = tail, to = (i <= end) ? end : es.length;
+                 ; i = 0, to = end) {
+                for (; i < to; i++)
+                    if (o.equals(es[i]))
+                        return true;
+                if (to == end) break;
             }
         }
         return false;
@@ -732,16 +1029,18 @@
      * The deque will be empty after this call returns.
      */
     public void clear() {
-        int h = head;
-        int t = tail;
-        if (h != t) { // clear all cells
-            head = tail = 0;
-            int i = h;
-            int mask = elements.length - 1;
-            do {
-                elements[i] = null;
-                i = (i + 1) & mask;
-            } while (i != t);
+        circularClear(elements, head, tail);
+        head = tail = 0;
+    }
+
+    /**
+     * Nulls out slots starting at array index i, upto index end.
+     */
+    private static void circularClear(Object[] es, int i, int end) {
+        for (int to = (i <= end) ? end : es.length;
+             ; i = 0, to = end) {
+            Arrays.fill(es, i, to, null);
+            if (to == end) break;
         }
     }
 
@@ -759,13 +1058,23 @@
      * @return an array containing all of the elements in this deque
      */
     public Object[] toArray() {
-        final int head = this.head;
-        final int tail = this.tail;
-        boolean wrap = (tail < head);
-        int end = wrap ? tail + elements.length : tail;
-        Object[] a = Arrays.copyOfRange(elements, head, end);
-        if (wrap)
-            System.arraycopy(elements, 0, a, elements.length - head, tail);
+        return toArray(Object[].class);
+    }
+
+    private <T> T[] toArray(Class<T[]> klazz) {
+        final Object[] es = elements;
+        final T[] a;
+        final int head = this.head, tail = this.tail, end;
+        if ((end = tail + ((head <= tail) ? 0 : es.length)) >= 0) {
+            // Uses null extension feature of copyOfRange
+            a = Arrays.copyOfRange(es, head, end, klazz);
+        } else {
+            // integer overflow!
+            a = Arrays.copyOfRange(es, 0, end - head, klazz);
+            System.arraycopy(es, head, a, 0, es.length - head);
+        }
+        if (end != tail)
+            System.arraycopy(es, 0, a, es.length - head, tail);
         return a;
     }
 
@@ -807,22 +1116,17 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        final int head = this.head;
-        final int tail = this.tail;
-        boolean wrap = (tail < head);
-        int size = (tail - head) + (wrap ? elements.length : 0);
-        int firstLeg = size - (wrap ? tail : 0);
-        int len = a.length;
-        if (size > len) {
-            a = (T[]) Arrays.copyOfRange(elements, head, head + size,
-                                         a.getClass());
-        } else {
-            System.arraycopy(elements, head, a, 0, firstLeg);
-            if (size < len)
-                a[size] = null;
+        final int size;
+        if ((size = size()) > a.length)
+            return toArray((Class<T[]>) a.getClass());
+        final Object[] es = elements;
+        for (int i = head, j = 0, len = Math.min(size, es.length - i);
+             ; i = 0, len = tail) {
+            System.arraycopy(es, i, a, j, len);
+            if ((j += len) == size) break;
         }
-        if (wrap)
-            System.arraycopy(elements, 0, a, firstLeg, tail);
+        if (size < a.length)
+            a[size] = null;
         return a;
     }
 
@@ -863,9 +1167,13 @@
         s.writeInt(size());
 
         // Write out elements in order.
-        int mask = elements.length - 1;
-        for (int i = head; i != tail; i = (i + 1) & mask)
-            s.writeObject(elements[i]);
+        final Object[] es = elements;
+        for (int i = head, end = tail, to = (i <= end) ? end : es.length;
+             ; i = 0, to = end) {
+            for (; i < to; i++)
+                s.writeObject(es[i]);
+            if (to == end) break;
+        }
     }
 
     /**
@@ -881,106 +1189,33 @@
 
         // Read in size and allocate array
         int size = s.readInt();
-        allocateElements(size);
-        head = 0;
-        tail = size;
+        elements = new Object[size + 1];
+        this.tail = size;
 
         // Read in all elements in the proper order.
         for (int i = 0; i < size; i++)
             elements[i] = s.readObject();
     }
 
-    /**
-     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
-     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
-     * deque.
-     *
-     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
-     * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
-     * {@link Spliterator#NONNULL}.  Overriding implementations should document
-     * the reporting of additional characteristic values.
-     *
-     * @return a {@code Spliterator} over the elements in this deque
-     * @since 1.8
-     */
-    public Spliterator<E> spliterator() {
-        return new DeqSpliterator<>(this, -1, -1);
-    }
-
-    static final class DeqSpliterator<E> implements Spliterator<E> {
-        private final ArrayDeque<E> deq;
-        private int fence;  // -1 until first use
-        private int index;  // current index, modified on traverse/split
-
-        /** Creates new spliterator covering the given array and range. */
-        DeqSpliterator(ArrayDeque<E> deq, int origin, int fence) {
-            this.deq = deq;
-            this.index = origin;
-            this.fence = fence;
-        }
-
-        private int getFence() { // force initialization
-            int t;
-            if ((t = fence) < 0) {
-                t = fence = deq.tail;
-                index = deq.head;
-            }
-            return t;
-        }
-
-        public DeqSpliterator<E> trySplit() {
-            int t = getFence(), h = index, n = deq.elements.length;
-            if (h != t && ((h + 1) & (n - 1)) != t) {
-                if (h > t)
-                    t += n;
-                int m = ((h + t) >>> 1) & (n - 1);
-                return new DeqSpliterator<E>(deq, h, index = m);
-            }
-            return null;
-        }
-
-        public void forEachRemaining(Consumer<? super E> consumer) {
-            if (consumer == null)
-                throw new NullPointerException();
-            Object[] a = deq.elements;
-            int m = a.length - 1, f = getFence(), i = index;
-            index = f;
-            while (i != f) {
-                @SuppressWarnings("unchecked") E e = (E)a[i];
-                i = (i + 1) & m;
-                if (e == null)
-                    throw new ConcurrentModificationException();
-                consumer.accept(e);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> consumer) {
-            if (consumer == null)
-                throw new NullPointerException();
-            Object[] a = deq.elements;
-            int m = a.length - 1, f = getFence(), i = index;
-            if (i != f) {
-                @SuppressWarnings("unchecked") E e = (E)a[i];
-                index = (i + 1) & m;
-                if (e == null)
-                    throw new ConcurrentModificationException();
-                consumer.accept(e);
-                return true;
-            }
-            return false;
-        }
-
-        public long estimateSize() {
-            int n = getFence() - index;
-            if (n < 0)
-                n += deq.elements.length;
-            return (long) n;
-        }
-
-        @Override
-        public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.SIZED |
-                Spliterator.NONNULL | Spliterator.SUBSIZED;
+    /** debugging */
+    void checkInvariants() {
+        // Use head and tail fields with empty slot at tail strategy.
+        // head == tail disambiguates to "empty".
+        try {
+            int capacity = elements.length;
+            // assert 0 <= head && head < capacity;
+            // assert 0 <= tail && tail < capacity;
+            // assert capacity > 0;
+            // assert size() < capacity;
+            // assert head == tail || elements[head] != null;
+            // assert elements[tail] == null;
+            // assert head == tail || elements[dec(tail, capacity)] != null;
+        } catch (Throwable t) {
+            System.err.printf("head=%d tail=%d capacity=%d%n",
+                              head, tail, elements.length);
+            System.err.printf("elements=%s%n",
+                              Arrays.toString(elements));
+            throw t;
         }
     }
 
diff --git a/jdk/src/java.base/share/classes/java/util/ArrayList.java b/jdk/src/java.base/share/classes/java/util/ArrayList.java
index d58047c..732b964 100644
--- a/jdk/src/java.base/share/classes/java/util/ArrayList.java
+++ b/jdk/src/java.base/share/classes/java/util/ArrayList.java
@@ -104,7 +104,6 @@
  * @see     Vector
  * @since   1.2
  */
-
 public class ArrayList<E> extends AbstractList<E>
         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
 {
@@ -424,6 +423,11 @@
         return (E) elementData[index];
     }
 
+    @SuppressWarnings("unchecked")
+    static <E> E elementAt(Object[] es, int index) {
+        return (E) es[index];
+    }
+
     /**
      * Returns the element at the specified position in this list.
      *
@@ -553,7 +557,7 @@
         return false;
     }
 
-    /*
+    /**
      * Private remove method that skips bounds checking and does not
      * return the value removed.
      */
@@ -572,11 +576,7 @@
      */
     public void clear() {
         modCount++;
-
-        // clear to let GC do its work
-        for (int i = 0; i < size; i++)
-            elementData[i] = null;
-
+        Arrays.fill(elementData, 0, size, null);
         size = 0;
     }
 
@@ -665,16 +665,10 @@
                     outOfBoundsMsg(fromIndex, toIndex));
         }
         modCount++;
-        int numMoved = size - toIndex;
-        System.arraycopy(elementData, toIndex, elementData, fromIndex,
-                         numMoved);
-
-        // clear to let GC do its work
-        int newSize = size - (toIndex-fromIndex);
-        for (int i = newSize; i < size; i++) {
-            elementData[i] = null;
-        }
-        size = newSize;
+        final Object[] es = elementData;
+        final int oldSize = size;
+        System.arraycopy(es, toIndex, es, fromIndex, oldSize - toIndex);
+        Arrays.fill(es, size -= (toIndex - fromIndex), oldSize, null);
     }
 
     /**
@@ -717,8 +711,7 @@
      * @see Collection#contains(Object)
      */
     public boolean removeAll(Collection<?> c) {
-        Objects.requireNonNull(c);
-        return batchRemove(c, false);
+        return batchRemove(c, false, 0, size);
     }
 
     /**
@@ -738,34 +731,35 @@
      * @see Collection#contains(Object)
      */
     public boolean retainAll(Collection<?> c) {
-        Objects.requireNonNull(c);
-        return batchRemove(c, true);
+        return batchRemove(c, true, 0, size);
     }
 
-    private boolean batchRemove(Collection<?> c, boolean complement) {
-        final Object[] elementData = this.elementData;
-        int r = 0, w = 0;
-        boolean modified = false;
-        try {
-            for (; r < size; r++)
-                if (c.contains(elementData[r]) == complement)
-                    elementData[w++] = elementData[r];
-        } finally {
-            // Preserve behavioral compatibility with AbstractCollection,
-            // even if c.contains() throws.
-            if (r != size) {
-                System.arraycopy(elementData, r,
-                                 elementData, w,
-                                 size - r);
-                w += size - r;
-            }
-            if (w != size) {
-                // clear to let GC do its work
-                for (int i = w; i < size; i++)
-                    elementData[i] = null;
-                modCount += size - w;
-                size = w;
-                modified = true;
+    boolean batchRemove(Collection<?> c, boolean complement,
+                        final int from, final int end) {
+        Objects.requireNonNull(c);
+        final Object[] es = elementData;
+        final boolean modified;
+        int r;
+        // Optimize for initial run of survivors
+        for (r = from; r < end && c.contains(es[r]) == complement; r++)
+            ;
+        if (modified = (r < end)) {
+            int w = r++;
+            try {
+                for (Object e; r < end; r++)
+                    if (c.contains(e = es[r]) == complement)
+                        es[w++] = e;
+            } catch (Throwable ex) {
+                // Preserve behavioral compatibility with AbstractCollection,
+                // even if c.contains() throws.
+                System.arraycopy(es, r, es, w, end - r);
+                w += end - r;
+                throw ex;
+            } finally {
+                final int oldSize = size, deleted = end - w;
+                modCount += deleted;
+                System.arraycopy(es, end, es, w, oldSize - end);
+                Arrays.fill(es, size -= deleted, oldSize, null);
             }
         }
         return modified;
@@ -912,25 +906,21 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
-        public void forEachRemaining(Consumer<? super E> consumer) {
-            Objects.requireNonNull(consumer);
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
             final int size = ArrayList.this.size;
             int i = cursor;
-            if (i >= size) {
-                return;
+            if (i < size) {
+                final Object[] es = elementData;
+                if (i >= es.length)
+                    throw new ConcurrentModificationException();
+                for (; i < size && modCount == expectedModCount; i++)
+                    action.accept(elementAt(es, i));
+                // update once at end to reduce heap write traffic
+                cursor = i;
+                lastRet = i - 1;
+                checkForComodification();
             }
-            final Object[] elementData = ArrayList.this.elementData;
-            if (i >= elementData.length) {
-                throw new ConcurrentModificationException();
-            }
-            while (i != size && modCount == expectedModCount) {
-                consumer.accept((E) elementData[i++]);
-            }
-            // update once at end of iteration to reduce heap write traffic
-            cursor = i;
-            lastRet = i - 1;
-            checkForComodification();
         }
 
         final void checkForComodification() {
@@ -1117,6 +1107,33 @@
             return true;
         }
 
+        public boolean removeAll(Collection<?> c) {
+            return batchRemove(c, false);
+        }
+
+        public boolean retainAll(Collection<?> c) {
+            return batchRemove(c, true);
+        }
+
+        private boolean batchRemove(Collection<?> c, boolean complement) {
+            checkForComodification();
+            int oldSize = root.size;
+            boolean modified =
+                root.batchRemove(c, complement, offset, offset + size);
+            if (modified)
+                updateSizeAndModCount(root.size - oldSize);
+            return modified;
+        }
+
+        public boolean removeIf(Predicate<? super E> filter) {
+            checkForComodification();
+            int oldSize = root.size;
+            boolean modified = root.removeIf(filter, offset, offset + size);
+            if (modified)
+                updateSizeAndModCount(root.size - oldSize);
+            return modified;
+        }
+
         public Iterator<E> iterator() {
             return listIterator();
         }
@@ -1164,24 +1181,21 @@
                     return (E) elementData[offset + (lastRet = i)];
                 }
 
-                @SuppressWarnings("unchecked")
-                public void forEachRemaining(Consumer<? super E> consumer) {
-                    Objects.requireNonNull(consumer);
+                public void forEachRemaining(Consumer<? super E> action) {
+                    Objects.requireNonNull(action);
                     final int size = SubList.this.size;
                     int i = cursor;
-                    if (i >= size) {
-                        return;
+                    if (i < size) {
+                        final Object[] es = root.elementData;
+                        if (offset + i >= es.length)
+                            throw new ConcurrentModificationException();
+                        for (; i < size && modCount == expectedModCount; i++)
+                            action.accept(elementAt(es, offset + i));
+                        // update once at end to reduce heap write traffic
+                        cursor = i;
+                        lastRet = i - 1;
+                        checkForComodification();
                     }
-                    final Object[] elementData = root.elementData;
-                    if (offset + i >= elementData.length) {
-                        throw new ConcurrentModificationException();
-                    }
-                    while (i != size && modCount == expectedModCount) {
-                        consumer.accept((E) elementData[offset + (i++)]);
-                    }
-                    // update once at end of iteration to reduce heap write traffic
-                    lastRet = cursor = i;
-                    checkForComodification();
                 }
 
                 public int nextIndex() {
@@ -1348,15 +1362,12 @@
     public void forEach(Consumer<? super E> action) {
         Objects.requireNonNull(action);
         final int expectedModCount = modCount;
-        @SuppressWarnings("unchecked")
-        final E[] elementData = (E[]) this.elementData;
+        final Object[] es = elementData;
         final int size = this.size;
-        for (int i=0; modCount == expectedModCount && i < size; i++) {
-            action.accept(elementData[i]);
-        }
-        if (modCount != expectedModCount) {
+        for (int i = 0; modCount == expectedModCount && i < size; i++)
+            action.accept(elementAt(es, i));
+        if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
-        }
     }
 
     /**
@@ -1417,7 +1428,7 @@
         private int fence; // -1 until used; then one past last index
         private int expectedModCount; // initialized when fence set
 
-        /** Create new spliterator covering the given  range */
+        /** Create new spliterator covering the given range */
         ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                              int expectedModCount) {
             this.list = list; // OK if null unless traversed
@@ -1495,61 +1506,73 @@
         }
     }
 
-    @Override
-    public boolean removeIf(Predicate<? super E> filter) {
-        Objects.requireNonNull(filter);
-        // figure out which elements are to be removed
-        // any exception thrown from the filter predicate at this stage
-        // will leave the collection unmodified
-        int removeCount = 0;
-        final BitSet removeSet = new BitSet(size);
-        final int expectedModCount = modCount;
-        final int size = this.size;
-        for (int i=0; modCount == expectedModCount && i < size; i++) {
-            @SuppressWarnings("unchecked")
-            final E element = (E) elementData[i];
-            if (filter.test(element)) {
-                removeSet.set(i);
-                removeCount++;
-            }
-        }
-        if (modCount != expectedModCount) {
-            throw new ConcurrentModificationException();
-        }
+    // A tiny bit set implementation
 
-        // shift surviving elements left over the spaces left by removed elements
-        final boolean anyToRemove = removeCount > 0;
-        if (anyToRemove) {
-            final int newSize = size - removeCount;
-            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
-                i = removeSet.nextClearBit(i);
-                elementData[j] = elementData[i];
-            }
-            for (int k=newSize; k < size; k++) {
-                elementData[k] = null;  // Let gc do its work
-            }
-            this.size = newSize;
-            if (modCount != expectedModCount) {
-                throw new ConcurrentModificationException();
-            }
-            modCount++;
-        }
-
-        return anyToRemove;
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
     }
 
     @Override
-    @SuppressWarnings("unchecked")
+    public boolean removeIf(Predicate<? super E> filter) {
+        return removeIf(filter, 0, size);
+    }
+
+    /**
+     * Removes all elements satisfying the given predicate, from index
+     * i (inclusive) to index end (exclusive).
+     */
+    boolean removeIf(Predicate<? super E> filter, int i, final int end) {
+        Objects.requireNonNull(filter);
+        int expectedModCount = modCount;
+        final Object[] es = elementData;
+        // Optimize for initial run of survivors
+        for (; i < end && !filter.test(elementAt(es, i)); i++)
+            ;
+        // Tolerate predicates that reentrantly access the collection for
+        // read (but writers still get CME), so traverse once to find
+        // elements to delete, a second pass to physically expunge.
+        if (i < end) {
+            final int beg = i;
+            final long[] deathRow = nBits(end - beg);
+            deathRow[0] = 1L;   // set bit 0
+            for (i = beg + 1; i < end; i++)
+                if (filter.test(elementAt(es, i)))
+                    setBit(deathRow, i - beg);
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            expectedModCount++;
+            modCount++;
+            int w = beg;
+            for (i = beg; i < end; i++)
+                if (isClear(deathRow, i - beg))
+                    es[w++] = es[i];
+            final int oldSize = size;
+            System.arraycopy(es, end, es, w, oldSize - end);
+            Arrays.fill(es, size -= (end - w), oldSize, null);
+            return true;
+        } else {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            return false;
+        }
+    }
+
+    @Override
     public void replaceAll(UnaryOperator<E> operator) {
         Objects.requireNonNull(operator);
         final int expectedModCount = modCount;
+        final Object[] es = elementData;
         final int size = this.size;
-        for (int i=0; modCount == expectedModCount && i < size; i++) {
-            elementData[i] = operator.apply((E) elementData[i]);
-        }
-        if (modCount != expectedModCount) {
+        for (int i = 0; modCount == expectedModCount && i < size; i++)
+            es[i] = operator.apply(elementAt(es, i));
+        if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
-        }
         modCount++;
     }
 
@@ -1558,9 +1581,13 @@
     public void sort(Comparator<? super E> c) {
         final int expectedModCount = modCount;
         Arrays.sort((E[]) elementData, 0, size, c);
-        if (modCount != expectedModCount) {
+        if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
-        }
         modCount++;
     }
+
+    void checkInvariants() {
+        // assert size >= 0;
+        // assert size == elementData.length || elementData[size] == null;
+    }
 }
diff --git a/jdk/src/java.base/share/classes/java/util/HashMap.java b/jdk/src/java.base/share/classes/java/util/HashMap.java
index fd4d9b1..5cc3629 100644
--- a/jdk/src/java.base/share/classes/java/util/HashMap.java
+++ b/jdk/src/java.base/share/classes/java/util/HashMap.java
@@ -1502,8 +1502,7 @@
             if (modCount != expectedModCount)
                 throw new ConcurrentModificationException();
             current = null;
-            K key = p.key;
-            removeNode(hash(key), key, null, false, false);
+            removeNode(p.hash, p.key, null, false, false);
             expectedModCount = modCount;
         }
     }
diff --git a/jdk/src/java.base/share/classes/java/util/Iterator.java b/jdk/src/java.base/share/classes/java/util/Iterator.java
index ca05cbb..7dcb155 100644
--- a/jdk/src/java.base/share/classes/java/util/Iterator.java
+++ b/jdk/src/java.base/share/classes/java/util/Iterator.java
@@ -76,10 +76,15 @@
     /**
      * Removes from the underlying collection the last element returned
      * by this iterator (optional operation).  This method can be called
-     * only once per call to {@link #next}.  The behavior of an iterator
-     * is unspecified if the underlying collection is modified while the
-     * iteration is in progress in any way other than by calling this
-     * method.
+     * only once per call to {@link #next}.
+     * <p>
+     * The behavior of an iterator is unspecified if the underlying collection
+     * is modified while the iteration is in progress in any way other than by
+     * calling this method, unless an overriding class has specified a
+     * concurrent modification policy.
+     * <p>
+     * The behavior of an iterator is unspecified if this method is called
+     * after a call to the {@link #forEachRemaining forEachRemaining} method.
      *
      * @implSpec
      * The default implementation throws an instance of
@@ -102,6 +107,13 @@
      * have been processed or the action throws an exception.  Actions are
      * performed in the order of iteration, if that order is specified.
      * Exceptions thrown by the action are relayed to the caller.
+     * <p>
+     * The behavior of an iterator is unspecified if the action modifies the
+     * collection in any way (even by calling the {@link #remove remove} method),
+     * unless an overriding class has specified a concurrent modification policy.
+     * <p>
+     * Subsequent behavior of an iterator is unspecified if the action throws an
+     * exception.
      *
      * @implSpec
      * <p>The default implementation behaves as if:
diff --git a/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java b/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java
index 0253cd5..bd21f5b 100644
--- a/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java
+++ b/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java
@@ -731,8 +731,7 @@
             if (modCount != expectedModCount)
                 throw new ConcurrentModificationException();
             current = null;
-            K key = p.key;
-            removeNode(hash(key), key, null, false, false);
+            removeNode(p.hash, p.key, null, false, false);
             expectedModCount = modCount;
         }
     }
diff --git a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
index 1d84e2d..f044526 100644
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java
@@ -42,6 +42,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
@@ -62,13 +63,14 @@
 import java.util.spi.ResourceBundleControlProvider;
 import java.util.spi.ResourceBundleProvider;
 
+import jdk.internal.loader.BootLoader;
 import jdk.internal.misc.JavaUtilResourceBundleAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
+import sun.security.action.GetPropertyAction;
 import sun.util.locale.BaseLocale;
 import sun.util.locale.LocaleObjectCache;
-import sun.util.locale.provider.ResourceBundleProviderSupport;
 import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
 
 
@@ -247,7 +249,8 @@
  * used to load resource bundles. If no service provider is available, or if
  * none of the service providers returns a resource bundle and the caller module
  * doesn't have its own service provider, the {@code getBundle} factory method
- * searches for resource bundles local to the caller module. The resource bundle
+ * searches for resource bundles that are local in the caller module and that
+ * are visible to the class loader of the caller module.  The resource bundle
  * formats for local module searching are "java.class" and "java.properties".
  *
  * <h3>ResourceBundle.Control</h3>
@@ -372,6 +375,18 @@
                 public void setName(ResourceBundle bundle, String name) {
                     bundle.name = name;
                 }
+
+                @Override
+                public ResourceBundle getBundle(String baseName, Locale locale, Module module) {
+                    // use the given module as the caller to bypass the access check
+                    return getBundleImpl(module, module, getLoader(module),
+                                         baseName, locale, Control.INSTANCE);
+                }
+
+                @Override
+                public ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) {
+                    return ResourceBundleProviderHelper.newResourceBundle(bundleClass);
+                }
             });
     }
 
@@ -999,6 +1014,14 @@
      * <code>getBundle(baseName, Locale.getDefault(), module)</code>
      * </blockquote>
      *
+     * <p> Resource bundles in named modules may be encapsulated.  When
+     * the resource bundle is loaded from a provider, the caller module
+     * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
+     * to declare that the module uses implementations of {@code "baseName"Provider}.
+     * When the resource bundle is loaded from the specified module, it is
+     * subject to the encapsulation rules specified by
+     * {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     *
      * @param baseName the base name of the resource bundle,
      *                 a fully qualified class name
      * @param module   the module for which the resource bundle is searched
@@ -1024,10 +1047,19 @@
      * Gets a resource bundle using the specified base name and locale
      * on behalf of the specified module.
      *
+     * <p> Resource bundles in named modules may be encapsulated.  When
+     * the resource bundle is loaded from a provider, the caller module
+     * must have an appropriate <i>uses</i> clause in its <i>module descriptor</i>
+     * to declare that the module uses implementations of {@code "baseName"Provider}.
+     * When the resource bundle is loaded from the specified module, it is
+     * subject to the encapsulation rules specified by
+     * {@link Module#getResourceAsStream Module.getResourceAsStream}.
+     *
      * <p>
      * If the given {@code module} is a named module, this method will
      * load the service providers for {@link java.util.spi.ResourceBundleProvider}
-     * and also resource bundles local in the given module (refer to the
+     * and also resource bundles that are local in the given module or that
+     * are visible to the class loader of the given module (refer to the
      * <a href="#bundleprovider">Resource Bundles in Named Modules</a> section
      * for details).
      *
@@ -1035,9 +1067,8 @@
      * If the given {@code module} is an unnamed module, then this method is
      * equivalent to calling {@link #getBundle(String, Locale, ClassLoader)
      * getBundle(baseName, targetLocale, module.getClassLoader()} to load
-     * resource bundles that are in unnamed modules visible to the
-     * class loader of the given unnamed module.  It will not find resource
-     * bundles from named modules.
+     * resource bundles that are visible to the class loader of the given
+     * unnamed module.
      *
      * @param baseName the base name of the resource bundle,
      *                 a fully qualified class name
@@ -1126,7 +1157,8 @@
      * Resource bundles in a named module are private to that module.  If
      * the caller is in a named module, this method will find resource bundles
      * from the service providers of {@link java.util.spi.ResourceBundleProvider}
-     * and also find resource bundles private to the caller's module.
+     * and also find resource bundles that are in the caller's module or
+     * that are visible to the given class loader.
      * If the caller is in a named module and the given {@code loader} is
      * different than the caller's class loader, or if the caller is not in
      * a named module, this method will not find resource bundles from named
@@ -1587,13 +1619,20 @@
             // get resource bundles for a named module only
             // if loader is the module's class loader
             if (loader == ml || (ml == null && loader == RBClassLoader.INSTANCE)) {
-                return getBundleImpl(baseName, locale, loader, module, control);
+                return getBundleImpl(module, module, loader, baseName, locale, control);
             }
         }
         // find resource bundles from unnamed module
-        Module module = loader != null ? loader.getUnnamedModule()
-                                       : ClassLoader.getSystemClassLoader().getUnnamedModule();
-        return getBundleImpl(baseName, locale, loader, module, control);
+        Module unnamedModule = loader != null
+            ? loader.getUnnamedModule()
+            : ClassLoader.getSystemClassLoader().getUnnamedModule();
+
+        if (caller == null) {
+            throw new InternalError("null caller");
+        }
+
+        Module callerModule = caller.getModule();
+        return getBundleImpl(callerModule, unnamedModule, loader, baseName, locale, control);
     }
 
     private static ResourceBundle getBundleFromModule(Class<?> caller,
@@ -1602,19 +1641,21 @@
                                                       Locale locale,
                                                       Control control) {
         Objects.requireNonNull(module);
-        if (caller.getModule() != module) {
+        Module callerModule = caller.getModule();
+        if (callerModule != module) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(GET_CLASSLOADER_PERMISSION);
             }
         }
-        return getBundleImpl(baseName, locale, getLoader(module), module, control);
+        return getBundleImpl(callerModule, module, getLoader(module), baseName, locale, control);
     }
 
-    private static ResourceBundle getBundleImpl(String baseName,
-                                                Locale locale,
-                                                ClassLoader loader,
+    private static ResourceBundle getBundleImpl(Module callerModule,
                                                 Module module,
+                                                ClassLoader loader,
+                                                String baseName,
+                                                Locale locale,
                                                 Control control) {
         if (locale == null || control == null) {
             throw new NullPointerException();
@@ -1661,7 +1702,8 @@
                 throw new IllegalArgumentException("Invalid Control: getCandidateLocales");
             }
 
-            bundle = findBundle(cacheKey, module, candidateLocales, formats, 0, control, baseBundle);
+            bundle = findBundle(callerModule, module, cacheKey,
+                                candidateLocales, formats, 0, control, baseBundle);
 
             // If the loaded bundle is the base bundle and exactly for the
             // requested locale or the only candidate locale, then take the
@@ -1710,8 +1752,9 @@
         return valid;
     }
 
-    private static ResourceBundle findBundle(CacheKey cacheKey,
+    private static ResourceBundle findBundle(Module callerModule,
                                              Module module,
+                                             CacheKey cacheKey,
                                              List<Locale> candidateLocales,
                                              List<String> formats,
                                              int index,
@@ -1720,7 +1763,8 @@
         Locale targetLocale = candidateLocales.get(index);
         ResourceBundle parent = null;
         if (index != candidateLocales.size() - 1) {
-            parent = findBundle(cacheKey, module, candidateLocales, formats, index + 1,
+            parent = findBundle(callerModule, module, cacheKey,
+                                candidateLocales, formats, index + 1,
                                 control, baseBundle);
         } else if (baseBundle != null && Locale.ROOT.equals(targetLocale)) {
             return baseBundle;
@@ -1764,10 +1808,10 @@
 
         if (bundle != NONEXISTENT_BUNDLE) {
             CacheKey constKey = (CacheKey) cacheKey.clone();
-
+            trace("findBundle: %d %s %s formats: %s%n", index, candidateLocales, cacheKey, formats);
             try {
                 if (module.isNamed()) {
-                    bundle = loadBundle(cacheKey, formats, control, module);
+                    bundle = loadBundle(cacheKey, formats, control, module, callerModule);
                 } else {
                     bundle = loadBundle(cacheKey, formats, control, expiredBundle);
                 }
@@ -1794,39 +1838,60 @@
 
     private static final String UNKNOWN_FORMAT = "";
 
+
     /*
      * Loads a ResourceBundle in named modules
      */
     private static ResourceBundle loadBundle(CacheKey cacheKey,
                                              List<String> formats,
                                              Control control,
-                                             Module module) {
+                                             Module module,
+                                             Module callerModule) {
         String baseName = cacheKey.getName();
         Locale targetLocale = cacheKey.getLocale();
 
         ResourceBundle bundle = null;
         if (cacheKey.hasProviders()) {
-            bundle = loadBundleFromProviders(baseName, targetLocale,
-                                             cacheKey.getProviders(), cacheKey);
+            if (callerModule == module) {
+                bundle = loadBundleFromProviders(baseName,
+                                                 targetLocale,
+                                                 cacheKey.getProviders(),
+                                                 cacheKey);
+            } else {
+                // load from provider if the caller module has access to the
+                // service type and also declares `uses`
+                ClassLoader loader = getLoader(module);
+                Class<ResourceBundleProvider> svc =
+                    getResourceBundleProviderType(baseName, loader);
+                if (svc != null
+                        && Reflection.verifyModuleAccess(callerModule, svc)
+                        && callerModule.canUse(svc)) {
+                    bundle = loadBundleFromProviders(baseName,
+                                                     targetLocale,
+                                                     cacheKey.getProviders(),
+                                                      cacheKey);
+                }
+            }
+
             if (bundle != null) {
                 cacheKey.setFormat(UNKNOWN_FORMAT);
             }
         }
+
         // If none of providers returned a bundle and the caller has no provider,
-        // look up module-local bundles.
+        // look up module-local bundles or from the class path
         if (bundle == null && !cacheKey.callerHasProvider()) {
-            String bundleName = control.toBundleName(baseName, targetLocale);
             for (String format : formats) {
                 try {
                     switch (format) {
                     case "java.class":
-                        PrivilegedAction<ResourceBundle> pa = ()
-                                -> ResourceBundleProviderSupport
-                                    .loadResourceBundle(module, bundleName);
-                        bundle = AccessController.doPrivileged(pa, null, GET_CLASSLOADER_PERMISSION);
+                        bundle = ResourceBundleProviderHelper
+                            .loadResourceBundle(callerModule, module, baseName, targetLocale);
+
                         break;
                     case "java.properties":
-                        bundle = ResourceBundleProviderSupport.loadPropertyResourceBundle(module, bundleName);
+                        bundle = ResourceBundleProviderHelper
+                            .loadPropertyResourceBundle(callerModule, module, baseName, targetLocale);
                         break;
                     default:
                         throw new InternalError("unexpected format: " + format);
@@ -1844,29 +1909,46 @@
         return bundle;
     }
 
+    /**
+     * Returns a ServiceLoader that will find providers that are bound to
+     * a given named module.
+     */
     private static ServiceLoader<ResourceBundleProvider> getServiceLoader(Module module,
-                                                                          String baseName) {
+                                                                          String baseName)
+    {
         if (!module.isNamed()) {
             return null;
         }
-        PrivilegedAction<ClassLoader> pa = module::getClassLoader;
-        ClassLoader loader = AccessController.doPrivileged(pa);
-        return getServiceLoader(module, loader, baseName);
+
+        ClassLoader loader = getLoader(module);
+        Class<ResourceBundleProvider> service =
+                getResourceBundleProviderType(baseName, loader);
+        if (service != null && Reflection.verifyModuleAccess(module, service)) {
+            try {
+                // locate providers that are visible to the class loader
+                // ServiceConfigurationError will be thrown if the module
+                // does not declare `uses` the service type
+                return ServiceLoader.load(service, loader, module);
+            } catch (ServiceConfigurationError e) {
+                // "uses" not declared
+                return null;
+            }
+        }
+        return null;
     }
 
-        /**
-         * Returns a ServiceLoader that will find providers that are bound to
-         * a given module that may be named or unnamed.
-         */
-    private static ServiceLoader<ResourceBundleProvider> getServiceLoader(Module module,
-                                                                          ClassLoader loader,
-                                                                          String baseName)
+    /**
+     * Returns the service type of the given baseName that is visible
+     * to the given class loader
+     */
+    private static Class<ResourceBundleProvider>
+            getResourceBundleProviderType(String baseName, ClassLoader loader)
     {
         // Look up <baseName> + "Provider"
         String providerName = baseName + "Provider";
         // Use the class loader of the getBundle caller so that the caller's
         // visibility of the provider type is checked.
-        Class<ResourceBundleProvider> service = AccessController.doPrivileged(
+        return AccessController.doPrivileged(
             new PrivilegedAction<>() {
                 @Override
                 public Class<ResourceBundleProvider> run() {
@@ -1881,16 +1963,6 @@
                     return null;
                 }
             });
-
-        if (service != null && Reflection.verifyModuleAccess(module, service)) {
-            try {
-                return ServiceLoader.load(service, loader, module);
-            } catch (ServiceConfigurationError e) {
-                // "uses" not declared: load bundle local in the module
-                return null;
-            }
-        }
-        return null;
     }
 
     /**
@@ -1914,6 +1986,7 @@
                                     cacheKey.callerHasProvider = Boolean.TRUE;
                                 }
                                 ResourceBundle bundle = provider.getBundle(baseName, locale);
+                                trace("provider %s %s locale: %s bundle: %s%n", provider, baseName, locale, bundle);
                                 if (bundle != null) {
                                     return bundle;
                                 }
@@ -3016,6 +3089,14 @@
          * indicates that this method is being called because the previously
          * loaded resource bundle has expired.
          *
+         * @implSpec
+         *
+         * Resource bundles in named modules are subject to the encapsulation
+         * rules specified by {@link Module#getResourceAsStream Module.getResourceAsStream}.
+         * A resource bundle in a named module visible to the given class loader
+         * is accessible when the package of the resource file corresponding
+         * to the resource bundle is open unconditionally.
+         *
          * <p>The default implementation instantiates a
          * <code>ResourceBundle</code> as follows.
          *
@@ -3026,12 +3107,15 @@
          * locale)}.</li>
          *
          * <li>If <code>format</code> is <code>"java.class"</code>, the
-         * {@link Class} specified by the bundle name is loaded by calling
-         * {@link ClassLoader#loadClass(String)}. Then, a
-         * <code>ResourceBundle</code> is instantiated by calling {@link
-         * Class#newInstance()}.  Note that the <code>reload</code> flag is
-         * ignored for loading class-based resource bundles in this default
-         * implementation.</li>
+         * {@link Class} specified by the bundle name is loaded with the
+         * given class loader. If the {@code Class} is found and accessible
+         * then the <code>ResourceBundle</code> is instantiated.  The
+         * resource bundle is accessible if the package of the bundle class file
+         * is open unconditionally; otherwise, {@code IllegalAccessException}
+         * will be thrown.
+         * Note that the <code>reload</code> flag is ignored for loading
+         * class-based resource bundles in this default implementation.
+         * </li>
          *
          * <li>If <code>format</code> is <code>"java.properties"</code>,
          * {@link #toResourceName(String, String) toResourceName(bundlename,
@@ -3105,7 +3189,6 @@
             /*
              * Legacy mechanism to locate resource bundle in unnamed module only
              * that is visible to the given loader and accessible to the given caller.
-             * This only finds resources on the class path but not in named modules.
              */
             String bundleName = toBundleName(baseName, locale);
             ResourceBundle bundle = null;
@@ -3117,18 +3200,15 @@
                     if (ResourceBundle.class.isAssignableFrom(c)) {
                         @SuppressWarnings("unchecked")
                         Class<ResourceBundle> bundleClass = (Class<ResourceBundle>)c;
+                        Module m = bundleClass.getModule();
 
-                        // This doesn't allow unnamed modules to find bundles in
-                        // named modules other than via the service loader mechanism.
-                        // Otherwise, this will make the newBundle method to be
-                        // caller-sensitive in order to verify access check.
-                        // So migrating resource bundles to named module can't
-                        // just export the package (in general, legacy resource
-                        // bundles have split package if they are packaged separate
-                        // from the consumer.)
-                        if (bundleClass.getModule().isNamed()) {
-                            throw new IllegalAccessException("unnamed modules can't load " + bundleName
-                                     + " in named module " + bundleClass.getModule().getName());
+                        // To access a resource bundle in a named module,
+                        // either class-based or properties-based, the resource
+                        // bundle must be opened unconditionally,
+                        // same rule as accessing a resource file.
+                        if (m.isNamed() && !m.isOpen(bundleClass.getPackageName())) {
+                            throw new IllegalAccessException("unnamed module can't load " +
+                                bundleClass.getName() + " in " + m.toString());
                         }
                         try {
                             // bundle in a unnamed module
@@ -3502,4 +3582,173 @@
             return null;
         }
     }
+
+    private static class ResourceBundleProviderHelper {
+        /**
+         * Returns a new ResourceBundle instance of the given bundleClass
+         */
+        static ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass) {
+            try {
+                @SuppressWarnings("unchecked")
+                Constructor<? extends ResourceBundle> ctor =
+                    bundleClass.getConstructor();
+                if (!Modifier.isPublic(ctor.getModifiers())) {
+                    return null;
+                }
+                // java.base may not be able to read the bundleClass's module.
+                PrivilegedAction<Void> pa = () -> { ctor.setAccessible(true); return null;};
+                AccessController.doPrivileged(pa);
+                try {
+                    return ctor.newInstance((Object[]) null);
+                } catch (InvocationTargetException e) {
+                    uncheckedThrow(e);
+                } catch (InstantiationException | IllegalAccessException e) {
+                    throw new InternalError(e);
+                }
+            } catch (NoSuchMethodException e) {
+                throw new InternalError(e);
+            }
+            return null;
+        }
+
+        /**
+         * Loads a {@code ResourceBundle} of the given {@code bundleName} local to
+         * the given {@code module}. If not found, search the bundle class
+         * that is visible from the module's class loader.
+         *
+         * The caller module is used for access check only.
+         */
+        static ResourceBundle loadResourceBundle(Module callerModule,
+                                                 Module module,
+                                                 String baseName,
+                                                 Locale locale)
+        {
+            String bundleName = Control.INSTANCE.toBundleName(baseName, locale);
+            try {
+                PrivilegedAction<Class<?>> pa = () -> Class.forName(module, bundleName);
+                Class<?> c = AccessController.doPrivileged(pa, null, GET_CLASSLOADER_PERMISSION);
+                trace("local in %s %s caller %s: %s%n", module, bundleName, callerModule, c);
+
+                if (c == null) {
+                    // if not found from the given module, locate resource bundle
+                    // that is visible to the module's class loader
+                    ClassLoader loader = getLoader(module);
+                    if (loader != null) {
+                        c = Class.forName(bundleName, false, loader);
+                    } else {
+                        c = BootLoader.loadClassOrNull(bundleName);
+                    }
+                    trace("loader for %s %s caller %s: %s%n", module, bundleName, callerModule, c);
+                }
+
+                if (c != null && ResourceBundle.class.isAssignableFrom(c)) {
+                    @SuppressWarnings("unchecked")
+                    Class<ResourceBundle> bundleClass = (Class<ResourceBundle>) c;
+                    Module m = bundleClass.getModule();
+                    if (!isAccessible(callerModule, m, bundleClass.getPackageName())) {
+                        trace("   %s does not have access to %s/%s%n", callerModule,
+                              m.getName(), bundleClass.getPackageName());
+                        return null;
+                    }
+
+                    return newResourceBundle(bundleClass);
+                }
+            } catch (ClassNotFoundException e) {}
+            return null;
+        }
+
+        /**
+         * Tests if resources of the given package name from the given module are
+         * open to the caller module.
+         */
+        static boolean isAccessible(Module callerModule, Module module, String pn) {
+            if (!module.isNamed() || callerModule == module)
+                return true;
+
+            return module.isOpen(pn, callerModule);
+        }
+
+        /**
+         * Loads properties of the given {@code bundleName} local in the given
+         * {@code module}.  If the .properties is not found or not open
+         * to the caller module to access, it will find the resource that
+         * is visible to the module's class loader.
+         *
+         * The caller module is used for access check only.
+         */
+        static ResourceBundle loadPropertyResourceBundle(Module callerModule,
+                                                         Module module,
+                                                         String baseName,
+                                                         Locale locale)
+            throws IOException
+        {
+            String bundleName = Control.INSTANCE.toBundleName(baseName, locale);
+
+            PrivilegedAction<InputStream> pa = () -> {
+                try {
+                    String resourceName = Control.INSTANCE
+                        .toResourceName0(bundleName, "properties");
+                    if (resourceName == null) {
+                        return null;
+                    }
+                    trace("local in %s %s caller %s%n", module, resourceName, callerModule);
+
+                    // if the package is in the given module but not opened
+                    // locate it from the given module first.
+                    String pn = toPackageName(bundleName);
+                    trace("   %s/%s is accessible to %s : %s%n",
+                            module.getName(), pn, callerModule,
+                            isAccessible(callerModule, module, pn));
+                    if (isAccessible(callerModule, module, pn)) {
+                        InputStream in = module.getResourceAsStream(resourceName);
+                        if (in != null) {
+                            return in;
+                        }
+                    }
+
+                    ClassLoader loader = module.getClassLoader();
+                    trace("loader for %s %s caller %s%n", module, resourceName, callerModule);
+
+                    try {
+                        if (loader != null) {
+                            return loader.getResourceAsStream(resourceName);
+                        } else {
+                            URL url = BootLoader.findResource(resourceName);
+                            if (url != null) {
+                                return url.openStream();
+                            }
+                        }
+                    } catch (Exception e) {}
+                    return null;
+
+                } catch (IOException e) {
+                    throw new UncheckedIOException(e);
+                }
+            };
+
+            try (InputStream stream = AccessController.doPrivileged(pa)) {
+                if (stream != null) {
+                    return new PropertyResourceBundle(stream);
+                } else {
+                    return null;
+                }
+            } catch (UncheckedIOException e) {
+                throw e.getCause();
+            }
+        }
+
+        private static String toPackageName(String bundleName) {
+            int i = bundleName.lastIndexOf('.');
+            return i != -1 ? bundleName.substring(0, i) : "";
+        }
+
+    }
+
+    private static final boolean TRACE_ON = Boolean.valueOf(
+        GetPropertyAction.privilegedGetProperty("resource.bundle.debug", "false"));
+
+    private static void trace(String format, Object... params) {
+        if (TRACE_ON)
+            System.out.format(format, params);
+    }
 }
diff --git a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
index 081b961..0b437d4 100644
--- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
+++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java
@@ -32,23 +32,28 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Layer;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Module;
 import java.net.URL;
 import java.net.URLConnection;
-import java.security.AccessController;
 import java.security.AccessControlContext;
+import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import jdk.internal.loader.BootLoader;
-import jdk.internal.loader.Loader;
-import jdk.internal.loader.LoaderPool;
 import jdk.internal.misc.JavaLangAccess;
+import jdk.internal.misc.JavaLangReflectModuleAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.VM;
 import jdk.internal.module.ServicesCatalog;
 import jdk.internal.module.ServicesCatalog.ServiceProvider;
-
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -76,21 +81,49 @@
  * request together with code that can create the actual provider on demand.
  * The details of provider classes tend to be highly service-specific; no
  * single class or interface could possibly unify them, so no such type is
- * defined here. A requirement enforced by this facility is that each provider
- * class must have a {@code public} zero-argument constructor.
+ * defined here.
+ *
+ * <p> Providers deployed as explicit modules on the module path are
+ * instantiated by a <em>provider factory</em> or directly via the provider's
+ * constructor. In the module declaration then the class name specified in the
+ * <i>provides</i> clause is a provider factory if it is public and defines a
+ * public static no-args method named "{@code provider}". The return type of
+ * the method must be assignable to the <i>service</i> type. If the class is
+ * not a provider factory then it is public with a public zero-argument
+ * constructor. The requirement that the provider factory or provider class
+ * be public helps to document the intent that the provider will be
+ * instantiated by the service-provider loading facility.
+ *
+ * <p> As an example, suppose a module declares the following:
+ *
+ * <pre>{@code
+ *     provides com.example.CodecSet with com.example.impl.StandardCodecs;
+ *     provides com.example.CodecSet with com.example.impl.ExtendedCodecsFactory;
+ * }</pre>
+ *
+ * <p> where {@code com.example.CodecSet} is the service type, {@code
+ * com.example.impl.StandardCodecs} is a provider class that is public with a
+ * public no-args constructor, {@code com.example.impl.ExtendedCodecsFactory}
+ * is a public class that defines a public static no-args method named
+ * "{@code provider}" with a return type that is {@code CodecSet} or a subtype
+ * of. For this example then {@code StandardCodecs}'s no-arg constructor will
+ * be used to instantiate {@code StandardCodecs}. {@code ExtendedCodecsFactory}
+ * will be treated as a provider factory and {@code
+ * ExtendedCodecsFactory.provider()} will be invoked to obtain the provider.
+ *
+ * <p> Providers deployed on the class path or as {@link
+ * java.lang.module.ModuleDescriptor#isAutomatic automatic-modules} on the
+ * module path must have a public zero-argument constructor.
  *
  * <p> An application or library using this loading facility and developed
- * and deployed as a named module must have an appropriate <i>uses</i> clause
- * in its <i>module descriptor</i> to declare that the module uses
+ * and deployed as an explicit module must have an appropriate <i>uses</i>
+ * clause in its <i>module descriptor</i> to declare that the module uses
  * implementations of the service. A corresponding requirement is that a
  * provider deployed as a named module must have an appropriate
  * <i>provides</i> clause in its module descriptor to declare that the module
  * provides an implementation of the service. The <i>uses</i> and
- * <i>provides</i> allow consumers of a service to be <i>linked</i> to
- * providers of the service. In the case of {@code load} methods that locate
- * service providers using a class loader, then provider modules defined to
- * that class loader, or a class loader <i>reachable</i> using {@link
- * ClassLoader#getParent() parent} delegation, will be located.
+ * <i>provides</i> allow consumers of a service to be <i>linked</i> to modules
+ * containing providers of the service.
  *
  * <p> A service provider that is packaged as a JAR file for the class path is
  * identified by placing a <i>provider-configuration file</i> in the resource
@@ -114,27 +147,116 @@
  *
  * <p> Providers are located and instantiated lazily, that is, on demand.  A
  * service loader maintains a cache of the providers that have been loaded so
- * far.  Each invocation of the {@link #iterator iterator} method returns an
- * iterator that first yields all of the elements of the cache, in
- * instantiation order, and then lazily locates and instantiates any remaining
- * providers, adding each one to the cache in turn.  The cache can be cleared
+ * far. Each invocation of the {@link #iterator iterator} method returns an
+ * iterator that first yields all of the elements cached from previous
+ * iteration, in instantiation order, and then lazily locates and instantiates
+ * any remaining providers, adding each one to the cache in turn.  Similarly,
+ * each invocation of the {@link #stream stream} method returns a stream that
+ * first processes all providers loaded by previous stream operations, in load
+ * order, and then lazily locates any remaining providers. Caches are cleared
  * via the {@link #reload reload} method.
  *
+ * <h2> Locating providers </h2>
+ *
+ * <p> The {@code load} methods locate providers using a class loader or module
+ * {@link Layer layer}. When locating providers using a class loader then
+ * providers in both named and unnamed modules may be located. When locating
+ * providers using a module layer then only providers in named modules in
+ * the layer (or parent layers) are located.
+ *
+ * <p> When locating providers using a class loader then any providers in named
+ * modules defined to the class loader, or any class loader that is reachable
+ * via parent delegation, are located. Additionally, providers in module layers
+ * other than the {@link Layer#boot() boot} layer, where the module layer
+ * contains modules defined to the class loader, or any class loader reachable
+ * via parent delegation, are also located. For example, suppose there is a
+ * module layer where each module is defined to its own class loader (see {@link
+ * Layer#defineModulesWithManyLoaders defineModulesWithManyLoaders}). If the
+ * {@code load} method is invoked to locate providers using any of these class
+ * loaders for this layer then it will locate all of the providers in that
+ * layer, irrespective of their defining class loader.
+ *
+ * <p> In the case of unnamed modules then the service configuration files are
+ * located using the class loader's {@link ClassLoader#getResources(String)
+ * ClassLoader.getResources(String)} method. Any providers listed should be
+ * visible via the class loader specified to the {@code load} method. If a
+ * provider in a named module is listed then it is ignored - this is to avoid
+ * duplicates that would otherwise arise when a module has both a
+ * <i>provides</i> clause and a service configuration file in {@code
+ * META-INF/services} that lists the same provider.
+ *
+ * <h2> Ordering </h2>
+ *
+ * <p> Service loaders created to locate providers using a {@code ClassLoader}
+ * locate providers as follows:
+ * <ul>
+ *     <li> Providers in named modules are located before providers on the
+ *     class path (or more generally, unnamed modules). </li>
+ *
+ *     <li> When locating providers in named modules then the service loader
+ *     will locate providers in modules defined to the class loader, then its
+ *     parent class loader, its parent parent, and so on to the bootstrap class
+ *     loader. If a {@code ClassLoader}, or any class loader in the parent
+ *     delegation chain, defines modules in a custom module {@link Layer} then
+ *     all providers in that layer are located, irrespective of their class
+ *     loader. The ordering of modules defined to the same class loader, or the
+ *     ordering of modules in a layer, is not defined. </li>
+ *
+ *     <li> If a named module declares more than one provider then the providers
+ *     are located in the order that they appear in the {@code provides} table of
+ *     the {@code Module} class file attribute ({@code module-info.class}). </li>
+ *
+ *     <li> When locating providers in unnamed modules then the ordering is
+ *     based on the order that the class loader's {@link
+ *     ClassLoader#getResources(String) ClassLoader.getResources(String)}
+ *     method finds the service configuration files. </li>
+ * </ul>
+ *
+ * <p> Service loaders created to locate providers in a module {@link Layer}
+ * will first locate providers in the layer, before locating providers in
+ * parent layers. Traversal of parent layers is depth-first with each layer
+ * visited at most once. For example, suppose L0 is the boot layer, L1 and
+ * L2 are custom layers with L0 as their parent. Now suppose that L3 is
+ * created with L1 and L2 as the parents (in that order). Using a service
+ * loader to locate providers with L3 as the content will locate providers
+ * in the following order: L3, L1, L0, L2. The ordering of modules in a layer
+ * is not defined.
+ *
+ * <h2> Selection and filtering </h2>
+ *
+ * <p> Selecting a provider or filtering providers will usually involve invoking
+ * a provider method. Where selection or filtering based on the provider class is
+ * needed then it can be done using a {@link #stream() stream}. For example, the
+ * following collects the providers that have a specific annotation:
+ * <pre>{@code
+ *     Set<CodecSet> providers = ServiceLoader.load(CodecSet.class)
+ *            .stream()
+ *            .filter(p -> p.type().isAnnotationPresent(Managed.class))
+ *            .map(Provider::get)
+ *            .collect(Collectors.toSet());
+ * }</pre>
+ *
+ * <h2> Security </h2>
+ *
  * <p> Service loaders always execute in the security context of the caller
- * of the iterator methods and may also be restricted by the security
+ * of the iterator or stream methods and may also be restricted by the security
  * context of the caller that created the service loader.
  * Trusted system code should typically invoke the methods in this class, and
  * the methods of the iterators which they return, from within a privileged
  * security context.
  *
+ * <h2> Concurrency </h2>
+ *
  * <p> Instances of this class are not safe for use by multiple concurrent
  * threads.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <h2> Null handling </h2>
+ *
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method in this class will cause a {@link NullPointerException} to be thrown.
  *
- * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
- * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
+ * <h2> Example </h2>
+ * <p> Suppose we have a service type <tt>com.example.CodecSet</tt> which is
  * intended to represent sets of encoder/decoder pairs for some protocol.  In
  * this case it is an abstract class with two abstract methods:
  *
@@ -218,11 +340,12 @@
 public final class ServiceLoader<S>
     implements Iterable<S>
 {
-    private static final String PREFIX = "META-INF/services/";
-
     // The class or interface representing the service being loaded
     private final Class<S> service;
 
+    // The class of the service type
+    private final String serviceName;
+
     // The module Layer used to locate providers; null when locating
     // providers using a class loader
     private final Layer layer;
@@ -234,75 +357,86 @@
     // The access control context taken when the ServiceLoader is created
     private final AccessControlContext acc;
 
-    // Cached providers, in instantiation order
-    private List<S> providers = new ArrayList<>();
+    // The lazy-lookup iterator for iterator operations
+    private Iterator<Provider<S>> lookupIterator1;
+    private final List<S> instantiatedProviders = new ArrayList<>();
 
-    // The class names of the cached providers, only used when locating
-    // service providers via a class loader
-    private Set<String> providerNames = new HashSet<>();
+    // The lazy-lookup iterator for stream operations
+    private Iterator<Provider<S>> lookupIterator2;
+    private final List<Provider<S>> loadedProviders = new ArrayList<>();
+    private boolean loadedAllProviders; // true when all providers loaded
 
     // Incremented when reload is called
     private int reloadCount;
 
-    // the service iterator when locating services via a module layer
-    private LayerLookupIterator layerLookupIterator;
-
-    // The module services iterator when locating services in modules
-    // defined to a class loader
-    private ModuleServicesIterator moduleServicesIterator;
-
-    // The current lazy-lookup iterator for locating legacy provider on the
-    // class path via a class loader
-    private LazyClassPathIterator lazyClassPathIterator;
-
-
-    /**
-     * Clear this loader's provider cache so that all providers will be
-     * reloaded.
-     *
-     * <p> After invoking this method, subsequent invocations of the {@link
-     * #iterator() iterator} method will lazily look up and instantiate
-     * providers from scratch, just as is done by a newly-created loader.
-     *
-     * <p> This method is intended for use in situations in which new providers
-     * can be installed into a running Java virtual machine.
-     */
-    public void reload() {
-        providers.clear();
-
-        assert layer == null || loader == null;
-        if (layer != null) {
-            layerLookupIterator = new LayerLookupIterator();
-        } else {
-            providerNames.clear();
-            moduleServicesIterator = new ModuleServicesIterator();
-            lazyClassPathIterator = new LazyClassPathIterator();
-        }
-
-        reloadCount++;
+    private static JavaLangAccess LANG_ACCESS;
+    private static JavaLangReflectModuleAccess JLRM_ACCESS;
+    static {
+        LANG_ACCESS = SharedSecrets.getJavaLangAccess();
+        JLRM_ACCESS = SharedSecrets.getJavaLangReflectModuleAccess();
     }
 
+    /**
+     * Represents a service provider located by {@code ServiceLoader}.
+     *
+     * <p> When using a loader's {@link ServiceLoader#stream() stream()} method
+     * then the elements are of type {@code Provider}. This allows processing
+     * to select or filter on the provider class without instantiating the
+     * provider. </p>
+     *
+     * @param  <S> The service type
+     * @since 9
+     */
+    public static interface Provider<S> extends Supplier<S> {
+        /**
+         * Returns the provider type. There is no guarantee that this type is
+         * accessible or that it has a public no-args constructor. The {@link
+         * #get() get()} method should be used to obtain the provider instance.
+         *
+         * <p> When a module declares that the provider class is created by a
+         * provider factory then this method returns the return type of its
+         * public static "{@code provider()}" method.
+         *
+         * @return The provider type
+         */
+        Class<? extends S> type();
+
+        /**
+         * Returns an instance of the provider.
+         *
+         * @return An instance of the provider.
+         *
+         * @throws ServiceConfigurationError
+         *         If the service provider cannot be instantiated, or in the
+         *         case of a provider factory, the public static
+         *         "{@code provider()}" method returns {@code null} or throws
+         *         an error or exception. The {@code ServiceConfigurationError}
+         *         will carry an appropriate cause where possible.
+         */
+        @Override S get();
+    }
 
     /**
      * Initializes a new instance of this class for locating service providers
      * in a module Layer.
      *
      * @throws ServiceConfigurationError
-     *         If {@code svc} is not accessible to {@code caller} or that the
-     *         caller's module does not declare that it uses the service type.
+     *         If {@code svc} is not accessible to {@code caller} or the caller
+     *         module does not use the service type.
      */
     private ServiceLoader(Class<?> caller, Layer layer, Class<S> svc) {
-
-        checkModule(caller.getModule(), svc);
+        Objects.requireNonNull(caller);
+        Objects.requireNonNull(layer);
+        Objects.requireNonNull(svc);
+        checkCaller(caller, svc);
 
         this.service = svc;
+        this.serviceName = svc.getName();
         this.layer = layer;
         this.loader = null;
         this.acc = (System.getSecurityManager() != null)
                 ? AccessController.getContext()
                 : null;
-
-        reload();
     }
 
     /**
@@ -310,23 +444,23 @@
      * via a class loader.
      *
      * @throws ServiceConfigurationError
-     *         If {@code svc} is not accessible to {@code caller} or that the
-     *         caller's module does not declare that it uses the service type.
+     *         If {@code svc} is not accessible to {@code caller} or the caller
+     *         module does not use the service type.
      */
-    private ServiceLoader(Module callerModule, Class<S> svc, ClassLoader cl) {
+    private ServiceLoader(Class<?> caller, Class<S> svc, ClassLoader cl) {
+        Objects.requireNonNull(svc);
+
         if (VM.isBooted()) {
-
-            checkModule(callerModule, svc);
-
+            checkCaller(caller, svc);
             if (cl == null) {
                 cl = ClassLoader.getSystemClassLoader();
             }
-
         } else {
 
             // if we get here then it means that ServiceLoader is being used
             // before the VM initialization has completed. At this point then
             // only code in the java.base should be executing.
+            Module callerModule = caller.getModule();
             Module base = Object.class.getModule();
             Module svcModule = svc.getModule();
             if (callerModule != base || svcModule != base) {
@@ -338,39 +472,55 @@
         }
 
         this.service = svc;
+        this.serviceName = svc.getName();
         this.layer = null;
         this.loader = cl;
         this.acc = (System.getSecurityManager() != null)
                 ? AccessController.getContext()
                 : null;
-
-        reload();
     }
 
-    private ServiceLoader(Class<?> caller, Class<S> svc, ClassLoader cl) {
-        this(caller.getModule(), svc, cl);
+    /**
+     * Initializes a new instance of this class for locating service providers
+     * via a class loader.
+     *
+     * @apiNote For use by ResourceBundle
+     *
+     * @throws ServiceConfigurationError
+     *         If the caller module does not use the service type.
+     */
+    private ServiceLoader(Module callerModule, Class<S> svc, ClassLoader cl) {
+        if (!callerModule.canUse(svc)) {
+            fail(svc, callerModule + " does not declare `uses`");
+        }
+
+        this.service = Objects.requireNonNull(svc);
+        this.serviceName = svc.getName();
+        this.layer = null;
+        this.loader = cl;
+        this.acc = (System.getSecurityManager() != null)
+                ? AccessController.getContext()
+                : null;
     }
 
-
-
     /**
      * Checks that the given service type is accessible to types in the given
-     * module, and check that the module declare that it uses the service type.
+     * module, and check that the module declare that it uses the service type. ??
      */
-    private static void checkModule(Module module, Class<?> svc) {
+    private static void checkCaller(Class<?> caller, Class<?> svc) {
+        Module callerModule = caller.getModule();
 
-        // Check that the service type is in a package that is
-        // exported to the caller.
-        if (!Reflection.verifyModuleAccess(module, svc)) {
-            fail(svc, "not accessible to " + module);
+        // Check access to the service type
+        int mods = svc.getModifiers();
+        if (!Reflection.verifyMemberAccess(caller, svc, null, mods)) {
+            fail(svc, "service type not accessible to " + callerModule);
         }
 
         // If the caller is in a named module then it should "uses" the
         // service type
-        if (!module.canUse(svc)) {
-            fail(svc, "use not declared in " + module);
+        if (!callerModule.canUse(svc)) {
+            fail(svc, callerModule + " does not declare `uses`");
         }
-
     }
 
     private static void fail(Class<?> service, String msg, Throwable cause)
@@ -392,310 +542,422 @@
         fail(service, u + ":" + line + ": " + msg);
     }
 
-    // Parse a single line from the given configuration file, adding the name
-    // on the line to the names list.
-    //
-    private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
-                          List<String> names)
-        throws IOException, ServiceConfigurationError
-    {
-        String ln = r.readLine();
-        if (ln == null) {
-            return -1;
-        }
-        int ci = ln.indexOf('#');
-        if (ci >= 0) ln = ln.substring(0, ci);
-        ln = ln.trim();
-        int n = ln.length();
-        if (n != 0) {
-            if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
-                fail(service, u, lc, "Illegal configuration-file syntax");
-            int cp = ln.codePointAt(0);
-            if (!Character.isJavaIdentifierStart(cp))
-                fail(service, u, lc, "Illegal provider-class name: " + ln);
-            for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
-                cp = ln.codePointAt(i);
-                if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
-                    fail(service, u, lc, "Illegal provider-class name: " + ln);
-            }
-            if (!providerNames.contains(ln) && !names.contains(ln))
-                names.add(ln);
-        }
-        return lc + 1;
-    }
-
     /**
-     * Parse the content of the given URL as a provider-configuration file.
-     *
-     * @param  service
-     *         The service type for which providers are being sought;
-     *         used to construct error detail strings
-     *
-     * @param  u
-     *         The URL naming the configuration file to be parsed
-     *
-     * @return A (possibly empty) iterator that will yield the provider-class
-     *         names in the given configuration file that are not yet members
-     *         of the returned set
+     * Uses Class.forName to load a provider class in a module.
      *
      * @throws ServiceConfigurationError
-     *         If an I/O error occurs while reading from the given URL, or
-     *         if a configuration-file format error is detected
-     *
+     *         If the class cannot be loaded
      */
-    private Iterator<String> parse(Class<?> service, URL u)
-        throws ServiceConfigurationError
-    {
-        ArrayList<String> names = new ArrayList<>();
-        try {
-            URLConnection uc = u.openConnection();
-            uc.setUseCaches(false);
-            try (InputStream in = uc.getInputStream();
-                 BufferedReader r
-                     = new BufferedReader(new InputStreamReader(in, "utf-8")))
-            {
-                int lc = 1;
-                while ((lc = parseLine(service, u, r, lc, names)) >= 0);
+    private Class<?> loadProviderInModule(Module module, String cn) {
+        Class<?> clazz = null;
+        if (acc == null) {
+            try {
+                clazz = Class.forName(module, cn);
+            } catch (LinkageError e) {
+                fail(service, "Unable to load " + cn, e);
             }
-        } catch (IOException x) {
-            fail(service, "Error accessing configuration file", x);
-        }
-        return names.iterator();
-    }
-
-    /**
-     * Returns the {@code Constructor} to instantiate the service provider.
-     * The constructor has its accessible flag set so that the access check
-     * is suppressed when instantiating the provider. This is necessary
-     * because newInstance is a caller sensitive method and ServiceLoader
-     * is instantiating the service provider on behalf of the service
-     * consumer.
-     */
-    private static Constructor<?> checkAndGetConstructor(Class<?> c)
-        throws NoSuchMethodException, IllegalAccessException
-    {
-        Constructor<?> ctor = c.getConstructor();
-
-        // check class and no-arg constructor are public
-        int modifiers = ctor.getModifiers();
-        if (!Modifier.isPublic(Reflection.getClassAccessFlags(c) & modifiers)) {
-            String cn = c.getName();
-            throw new IllegalAccessException(cn + " is not public");
-        }
-
-        // return Constructor to create the service implementation
-        PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
-            public Void run() { ctor.setAccessible(true); return null; }
-        };
-        AccessController.doPrivileged(action);
-        return ctor;
-    }
-
-    /**
-     * Uses Class.forName to load a class in a module.
-     */
-    private static Class<?> loadClassInModule(Module module, String cn) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm == null) {
-            return Class.forName(module, cn);
         } else {
-            PrivilegedAction<Class<?>> pa = () -> Class.forName(module, cn);
-            return AccessController.doPrivileged(pa);
+            PrivilegedExceptionAction<Class<?>> pa = () -> Class.forName(module, cn);
+            try {
+                clazz = AccessController.doPrivileged(pa);
+            } catch (PrivilegedActionException pae) {
+                Throwable x = pae.getCause();
+                fail(service, "Unable to load " + cn, x);
+                return null;
+            }
         }
+        if (clazz == null)
+            fail(service, "Provider " + cn  + " not found");
+        return clazz;
     }
 
     /**
-     * An Iterator that runs the next and hasNext methods with permissions
-     * restricted by the {@code AccessControlContext} obtained when the
-     * ServiceLoader was created.
+     * A Provider implementation that supports invoking, with reduced
+     * permissions, the static factory to obtain the provider or the
+     * provider's no-arg constructor.
      */
-    private abstract class RestrictedIterator<S>
-        implements Iterator<S>
-    {
-        /**
-         * Returns {@code true} if the iteration has more elements.
-         */
-        abstract boolean hasNextService();
+    private final static class ProviderImpl<S> implements Provider<S> {
+        final Class<S> service;
+        final AccessControlContext acc;
+
+        final Method factoryMethod;  // factory method or null
+        final Class<? extends S> type;
+        final Constructor<? extends S> ctor; // public no-args constructor or null
 
         /**
-         * Returns the next element in the iteration
+         * Creates a Provider.
+         *
+         * @param service
+         *        The service type
+         * @param clazz
+         *        The provider (or provider factory) class
+         * @param acc
+         *        The access control context when running with security manager
+         *
+         * @throws ServiceConfigurationError
+         *         If the class is not public; If the class defines a public
+         *         static provider() method with a return type that is assignable
+         *         to the service type or the class is not a provider class with
+         *         a public no-args constructor.
          */
-        abstract S nextService();
+        @SuppressWarnings("unchecked")
+        ProviderImpl(Class<?> service, Class<?> clazz, AccessControlContext acc) {
+            this.service = (Class<S>) service;
+            this.acc = acc;
 
-        public final boolean hasNext() {
-            if (acc == null) {
-                return hasNextService();
+            int mods = clazz.getModifiers();
+            if (!Modifier.isPublic(mods)) {
+                fail(service, clazz + " is not public");
+            }
+
+            // if the class is in an explicit module then see if it is
+            // a provider factory class
+            Method factoryMethod = null;
+            if (inExplicitModule(clazz)) {
+                factoryMethod = findStaticProviderMethod(clazz);
+                if (factoryMethod != null) {
+                    Class<?> returnType = factoryMethod.getReturnType();
+                    if (!service.isAssignableFrom(returnType)) {
+                        fail(service, factoryMethod + " return type not a subtype");
+                    }
+                }
+            }
+            this.factoryMethod = factoryMethod;
+
+            if (factoryMethod == null) {
+                // no factory method so must have a public no-args constructor
+                if (!service.isAssignableFrom(clazz)) {
+                    fail(service, clazz.getName() + " not a subtype");
+                }
+                this.type = (Class<? extends S>) clazz;
+                this.ctor = (Constructor<? extends S>) getConstructor(clazz);
             } else {
-                PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
-                    public Boolean run() { return hasNextService(); }
-                };
-                return AccessController.doPrivileged(action, acc);
+                this.type = (Class<? extends S>) factoryMethod.getReturnType();
+                this.ctor = null;
             }
         }
 
-        public final S next() {
-            if (acc == null) {
-                return nextService();
+        @Override
+        public Class<? extends S> type() {
+            return type;
+        }
+
+        @Override
+        public S get() {
+            if (factoryMethod != null) {
+                return invokeFactoryMethod();
             } else {
-                PrivilegedAction<S> action = new PrivilegedAction<S>() {
-                    public S run() { return nextService(); }
-                };
-                return AccessController.doPrivileged(action, acc);
+                return newInstance();
             }
         }
+
+        /**
+         * Returns {@code true} if the provider is in an explicit module
+         */
+        private boolean inExplicitModule(Class<?> clazz) {
+            Module module = clazz.getModule();
+            return module.isNamed() && !module.getDescriptor().isAutomatic();
+        }
+
+        /**
+         * Returns the public static provider method if found.
+         *
+         * @throws ServiceConfigurationError if there is an error finding the
+         *         provider method
+         */
+        private Method findStaticProviderMethod(Class<?> clazz) {
+            Method method = null;
+            try {
+                method = LANG_ACCESS.getMethodOrNull(clazz, "provider");
+            } catch (Throwable x) {
+                fail(service, "Unable to get public provider() method", x);
+            }
+            if (method != null) {
+                int mods = method.getModifiers();
+                if (Modifier.isStatic(mods)) {
+                    assert Modifier.isPublic(mods);
+                    Method m = method;
+                    PrivilegedAction<Void> pa = () -> {
+                        m.setAccessible(true);
+                        return null;
+                    };
+                    AccessController.doPrivileged(pa);
+                    return method;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Returns the public no-arg constructor of a class.
+         *
+         * @throws ServiceConfigurationError if the class does not have
+         *         public no-arg constructor
+         */
+        private Constructor<?> getConstructor(Class<?> clazz) {
+            PrivilegedExceptionAction<Constructor<?>> pa
+                = new PrivilegedExceptionAction<>() {
+                    @Override
+                    public Constructor<?> run() throws Exception {
+                        Constructor<?> ctor = clazz.getConstructor();
+                        if (inExplicitModule(clazz))
+                            ctor.setAccessible(true);
+                        return ctor;
+                    }
+                };
+            Constructor<?> ctor = null;
+            try {
+                ctor = AccessController.doPrivileged(pa);
+            } catch (Throwable x) {
+                if (x instanceof PrivilegedActionException)
+                    x = x.getCause();
+                String cn = clazz.getName();
+                fail(service, cn + " Unable to get public no-arg constructor", x);
+            }
+            return ctor;
+        }
+
+        /**
+         * Invokes the provider's "provider" method to instantiate a provider.
+         * When running with a security manager then the method runs with
+         * permissions that are restricted by the security context of whatever
+         * created this loader.
+         */
+        private S invokeFactoryMethod() {
+            Object result = null;
+            Throwable exc = null;
+            if (acc == null) {
+                try {
+                    result = factoryMethod.invoke(null);
+                } catch (Throwable x) {
+                    exc = x;
+                }
+            } else {
+                PrivilegedExceptionAction<?> pa = new PrivilegedExceptionAction<>() {
+                    @Override
+                    public Object run() throws Exception {
+                        return factoryMethod.invoke(null);
+                    }
+                };
+                // invoke factory method with permissions restricted by acc
+                try {
+                    result = AccessController.doPrivileged(pa, acc);
+                } catch (PrivilegedActionException pae) {
+                    exc = pae.getCause();
+                }
+            }
+            if (exc != null) {
+                if (exc instanceof InvocationTargetException)
+                    exc = exc.getCause();
+                fail(service, factoryMethod + " failed", exc);
+            }
+            if (result == null) {
+                fail(service, factoryMethod + " returned null");
+            }
+            @SuppressWarnings("unchecked")
+            S p = (S) result;
+            return p;
+        }
+
+        /**
+         * Invokes Constructor::newInstance to instantiate a provider. When running
+         * with a security manager then the constructor runs with permissions that
+         * are restricted by the security context of whatever created this loader.
+         */
+        private S newInstance() {
+            S p = null;
+            Throwable exc = null;
+            if (acc == null) {
+                try {
+                    p = ctor.newInstance();
+                } catch (Throwable x) {
+                    exc = x;
+                }
+            } else {
+                PrivilegedExceptionAction<S> pa = new PrivilegedExceptionAction<>() {
+                    @Override
+                    public S run() throws Exception {
+                        return ctor.newInstance();
+                    }
+                };
+                // invoke constructor with permissions restricted by acc
+                try {
+                    p = AccessController.doPrivileged(pa, acc);
+                } catch (PrivilegedActionException pae) {
+                    exc = pae.getCause();
+                }
+            }
+            if (exc != null) {
+                if (exc instanceof InvocationTargetException)
+                    exc = exc.getCause();
+                String cn = ctor.getDeclaringClass().getName();
+                fail(service,
+                     "Provider " + cn + " could not be instantiated", exc);
+            }
+            return p;
+        }
+
+        // For now, equals/hashCode uses the access control context to ensure
+        // that two Providers created with different contexts are not equal
+        // when running with a security manager.
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(type, acc);
+        }
+
+        @Override
+        public boolean equals(Object ob) {
+            if (!(ob instanceof ProviderImpl))
+                return false;
+            @SuppressWarnings("unchecked")
+            ProviderImpl<?> that = (ProviderImpl<?>)ob;
+            return this.type == that.type
+                    && Objects.equals(this.acc, that.acc);
+        }
     }
 
     /**
      * Implements lazy service provider lookup of service providers that
-     * are provided by modules in a module Layer.
+     * are provided by modules in a module Layer (or parent layers)
      */
-    private class LayerLookupIterator
-        extends RestrictedIterator<S>
+    private final class LayerLookupIterator<T>
+        implements Iterator<Provider<T>>
     {
-        final String serviceName;
-        Layer currentLayer;
+        Deque<Layer> stack = new ArrayDeque<>();
+        Set<Layer> visited = new HashSet<>();
         Iterator<ServiceProvider> iterator;
-        ServiceProvider nextProvider;
+        ServiceProvider next;  // next provider to load
 
         LayerLookupIterator() {
-            serviceName = service.getName();
-            currentLayer = layer;
-
-            // need to get us started
-            iterator = providers(currentLayer, serviceName);
+            visited.add(layer);
+            stack.push(layer);
         }
 
-        Iterator<ServiceProvider> providers(Layer layer, String service) {
-            ServicesCatalog catalog = SharedSecrets
-                    .getJavaLangReflectModuleAccess()
-                    .getServicesCatalog(layer);
-
+        private Iterator<ServiceProvider> providers(Layer layer) {
+            ServicesCatalog catalog = JLRM_ACCESS.getServicesCatalog(layer);
             return catalog.findServices(serviceName).iterator();
         }
 
         @Override
-        boolean hasNextService() {
-
+        public boolean hasNext() {
             // already have the next provider cached
-            if (nextProvider != null)
+            if (next != null)
                 return true;
 
             while (true) {
 
-                // next provider
+                // next provider (or provider factory)
                 if (iterator != null && iterator.hasNext()) {
-                    nextProvider = iterator.next();
+                    next = iterator.next();
                     return true;
                 }
 
-                // next layer
-                Layer parent = currentLayer.parent().orElse(null);
-                if (parent == null)
+                // next layer (DFS order)
+                if (stack.isEmpty())
                     return false;
 
-                currentLayer = parent;
-                iterator = providers(currentLayer, serviceName);
+                Layer layer = stack.pop();
+                List<Layer> parents = layer.parents();
+                for (int i = parents.size() - 1; i >= 0; i--) {
+                    Layer parent = parents.get(i);
+                    if (!visited.contains(parent)) {
+                        visited.add(parent);
+                        stack.push(parent);
+                    }
+                }
+                iterator = providers(layer);
             }
         }
 
         @Override
-        S nextService() {
-            if (!hasNextService())
+        public Provider<T> next() {
+            if (!hasNext())
                 throw new NoSuchElementException();
 
-            ServiceProvider provider = nextProvider;
-            nextProvider = null;
+            // take next provider
+            ServiceProvider provider = next;
+            next = null;
 
+            // attempt to load provider
             Module module = provider.module();
             String cn = provider.providerName();
-
-            // attempt to load the provider
-            Class<?> c = loadClassInModule(module, cn);
-            if (c == null)
-                fail(service, "Provider " + cn  + " not found");
-            if (!service.isAssignableFrom(c))
-                fail(service, "Provider " + cn  + " not a subtype");
-
-            // instantiate the provider
-            S p = null;
-            try {
-                Constructor<?> ctor = checkAndGetConstructor(c);
-                p = service.cast(ctor.newInstance());
-            } catch (Throwable x) {
-                if (x instanceof InvocationTargetException)
-                    x = x.getCause();
-                fail(service,
-                        "Provider " + cn + " could not be instantiated", x);
-            }
-
-            // add to cached provider list
-            providers.add(p);
-
-            return p;
+            Class<?> clazz = loadProviderInModule(module, cn);
+            return new ProviderImpl<T>(service, clazz, acc);
         }
     }
 
     /**
      * Implements lazy service provider lookup of service providers that
-     * are provided by modules defined to a class loader.
+     * are provided by modules defined to a class loader or to modules in
+     * layers with a module defined to the class loader.
      */
-    private class ModuleServicesIterator
-        extends RestrictedIterator<S>
+    private final class ModuleServicesLookupIterator<T>
+        implements Iterator<Provider<T>>
     {
-        final JavaLangAccess langAccess = SharedSecrets.getJavaLangAccess();
-
         ClassLoader currentLoader;
         Iterator<ServiceProvider> iterator;
-        ServiceProvider nextProvider;
+        ServiceProvider next;  // next provider to load
 
-        ModuleServicesIterator() {
+        ModuleServicesLookupIterator() {
             this.currentLoader = loader;
             this.iterator = iteratorFor(loader);
         }
 
         /**
+         * Returns iterator to iterate over the implementations of {@code
+         * service} in the given layer.
+         */
+        private List<ServiceProvider> providers(Layer layer) {
+            ServicesCatalog catalog = JLRM_ACCESS.getServicesCatalog(layer);
+            return catalog.findServices(serviceName);
+        }
+
+        /**
          * Returns an iterator to iterate over the implementations of {@code
-         * service} in modules defined to the given class loader.
+         * service} in modules defined to the given class loader or in custom
+         * layers with a module defined to this class loader.
          */
         private Iterator<ServiceProvider> iteratorFor(ClassLoader loader) {
 
-            // if the class loader is in a loader pool then return an Iterator
-            // that iterates over all service providers in the pool that provide
-            // an implementation of the service
-            if (currentLoader instanceof Loader) {
-                LoaderPool pool = ((Loader) loader).pool();
-                if (pool != null) {
-                    return pool.loaders()
-                            .map(l -> langAccess.getServicesCatalog(l))
-                            .filter(sc -> sc != null)
-                            .map(sc -> sc.findServices(service.getName()))
-                            .flatMap(Set::stream)
-                            .iterator();
-                }
-            }
-
+            // modules defined to this class loader
             ServicesCatalog catalog;
-            if (currentLoader == null) {
+            if (loader == null) {
                 catalog = BootLoader.getServicesCatalog();
             } else {
-                catalog = langAccess.getServicesCatalog(currentLoader);
+                catalog = ServicesCatalog.getServicesCatalogOrNull(loader);
             }
+            Stream<ServiceProvider> stream1;
             if (catalog == null) {
-                return Collections.emptyIterator();
+                stream1 = Stream.empty();
             } else {
-                return catalog.findServices(service.getName()).iterator();
+                stream1 = catalog.findServices(serviceName).stream();
             }
+
+            // modules in custom layers that define modules to the class loader
+            Stream<ServiceProvider> stream2;
+            if (loader == null) {
+                stream2 = Stream.empty();
+            } else {
+                Layer bootLayer = Layer.boot();
+                stream2 = JLRM_ACCESS.layers(loader)
+                        .filter(l -> (l != bootLayer))
+                        .map(l -> providers(l))
+                        .flatMap(List::stream);
+            }
+
+            return Stream.concat(stream1, stream2).iterator();
         }
 
         @Override
-        boolean hasNextService() {
+        public boolean hasNext() {
             // already have the next provider cached
-            if (nextProvider != null)
+            if (next != null)
                 return true;
 
             while (true) {
                 if (iterator.hasNext()) {
-                    nextProvider = iterator.next();
+                    next = iterator.next();
                     return true;
                 }
 
@@ -710,138 +972,220 @@
         }
 
         @Override
-        S nextService() {
-            if (!hasNextService())
+        public Provider<T> next() {
+            if (!hasNext())
                 throw new NoSuchElementException();
 
-            ServiceProvider provider = nextProvider;
-            nextProvider = null;
+            // take next provider
+            ServiceProvider provider = next;
+            next = null;
 
-            // attempt to load the provider
+            // attempt to load provider
             Module module = provider.module();
             String cn = provider.providerName();
-
-            Class<?> c = loadClassInModule(module, cn);
-            if (c == null) {
-                fail(service,
-                    "Provider " + cn + " not found in " + module.getName());
-            }
-            if (!service.isAssignableFrom(c)) {
-                fail(service, "Provider " + cn  + " not a subtype");
-            }
-
-            // instantiate the provider
-            S p = null;
-            try {
-                Constructor<?> ctor = checkAndGetConstructor(c);
-                p = service.cast(ctor.newInstance());
-            } catch (Throwable x) {
-                if (x instanceof InvocationTargetException)
-                    x = x.getCause();
-                fail(service,
-                    "Provider " + cn + " could not be instantiated", x);
-            }
-
-            // add to provider list
-            providers.add(p);
-
-            // record the class name of the service provider, this is
-            // needed for cases where there a module has both a "uses"
-            // and a services configuration file listing the same
-            // provider
-            providerNames.add(cn);
-
-            return p;
+            Class<?> clazz = loadProviderInModule(module, cn);
+            return new ProviderImpl<T>(service, clazz, acc);
         }
     }
 
     /**
-     * Implements lazy service provider lookup where the service providers
-     * are configured via service configuration files.
+     * Implements lazy service provider lookup where the service providers are
+     * configured via service configuration files. Service providers in named
+     * modules are silently ignored by this lookup iterator.
      */
-    private class LazyClassPathIterator
-        extends RestrictedIterator<S>
+    private final class LazyClassPathLookupIterator<T>
+        implements Iterator<Provider<T>>
     {
+        static final String PREFIX = "META-INF/services/";
+
         Enumeration<URL> configs;
         Iterator<String> pending;
-        String nextName;
+        Class<?> nextClass;
+        String nextErrorMessage;  // when hasNext fails with CNFE
 
-        @Override
-        boolean hasNextService() {
-            if (nextName != null) {
+        LazyClassPathLookupIterator() { }
+
+        /**
+         * Parse a single line from the given configuration file, adding the
+         * name on the line to the names list.
+         */
+        private int parseLine(URL u, BufferedReader r, int lc, Set<String> names)
+            throws IOException
+        {
+            String ln = r.readLine();
+            if (ln == null) {
+                return -1;
+            }
+            int ci = ln.indexOf('#');
+            if (ci >= 0) ln = ln.substring(0, ci);
+            ln = ln.trim();
+            int n = ln.length();
+            if (n != 0) {
+                if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
+                    fail(service, u, lc, "Illegal configuration-file syntax");
+                int cp = ln.codePointAt(0);
+                if (!Character.isJavaIdentifierStart(cp))
+                    fail(service, u, lc, "Illegal provider-class name: " + ln);
+                int start = Character.charCount(cp);
+                for (int i = start; i < n; i += Character.charCount(cp)) {
+                    cp = ln.codePointAt(i);
+                    if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
+                        fail(service, u, lc, "Illegal provider-class name: " + ln);
+                }
+                names.add(ln);
+            }
+            return lc + 1;
+        }
+
+        /**
+         * Parse the content of the given URL as a provider-configuration file.
+         */
+        private Iterator<String> parse(URL u) {
+            Set<String> names = new LinkedHashSet<>(); // preserve insertion order
+            try {
+                URLConnection uc = u.openConnection();
+                uc.setUseCaches(false);
+                try (InputStream in = uc.getInputStream();
+                     BufferedReader r
+                         = new BufferedReader(new InputStreamReader(in, "utf-8")))
+                {
+                    int lc = 1;
+                    while ((lc = parseLine(u, r, lc, names)) >= 0);
+                }
+            } catch (IOException x) {
+                fail(service, "Error accessing configuration file", x);
+            }
+            return names.iterator();
+        }
+
+        private boolean hasNextService() {
+            if (nextClass != null || nextErrorMessage != null) {
                 return true;
             }
-            if (configs == null) {
+
+            Class<?> clazz = null;
+            do {
+                if (configs == null) {
+                    try {
+                        String fullName = PREFIX + service.getName();
+                        if (loader == null)
+                            configs = ClassLoader.getSystemResources(fullName);
+                        else
+                            configs = loader.getResources(fullName);
+                    } catch (IOException x) {
+                        fail(service, "Error locating configuration files", x);
+                    }
+                }
+                while ((pending == null) || !pending.hasNext()) {
+                    if (!configs.hasMoreElements()) {
+                        return false;
+                    }
+                    pending = parse(configs.nextElement());
+                }
+                String cn = pending.next();
                 try {
-                    String fullName = PREFIX + service.getName();
-                    if (loader == null)
-                        configs = ClassLoader.getSystemResources(fullName);
-                    else
-                        configs = loader.getResources(fullName);
-                } catch (IOException x) {
-                    fail(service, "Error locating configuration files", x);
+                    clazz = Class.forName(cn, false, loader);
+                } catch (ClassNotFoundException x) {
+                    // don't throw SCE here to long standing behavior
+                    nextErrorMessage = "Provider " + cn + " not found";
+                    return true;
                 }
-            }
-            while ((pending == null) || !pending.hasNext()) {
-                if (!configs.hasMoreElements()) {
-                    return false;
-                }
-                pending = parse(service, configs.nextElement());
-            }
-            nextName = pending.next();
+
+            } while (clazz.getModule().isNamed()); // ignore if in named module
+
+            nextClass = clazz;
             return true;
         }
 
-        @Override
-        S nextService() {
+        private Provider<T> nextService() {
             if (!hasNextService())
                 throw new NoSuchElementException();
-            String cn = nextName;
-            nextName = null;
-            Class<?> c = null;
-            try {
-                c = Class.forName(cn, false, loader);
-            } catch (ClassNotFoundException x) {
-                fail(service,
-                     "Provider " + cn + " not found");
+
+            // throw any SCE with error recorded by hasNext
+            if (nextErrorMessage != null) {
+                String msg = nextErrorMessage;
+                nextErrorMessage = null;
+                fail(service, msg);
             }
-            if (!service.isAssignableFrom(c)) {
-                fail(service,
-                     "Provider " + cn  + " not a subtype");
+
+            // return next provider
+            Class<?> clazz = nextClass;
+            nextClass = null;
+            return new ProviderImpl<T>(service, clazz, acc);
+        }
+
+        @Override
+        public boolean hasNext() {
+            if (acc == null) {
+                return hasNextService();
+            } else {
+                PrivilegedAction<Boolean> action = new PrivilegedAction<>() {
+                    public Boolean run() { return hasNextService(); }
+                };
+                return AccessController.doPrivileged(action, acc);
             }
-            S p = null;
-            try {
-                @SuppressWarnings("deprecation")
-                Object tmp = c.newInstance();
-                p = service.cast(tmp);
-            } catch (Throwable x) {
-                fail(service,
-                     "Provider " + cn + " could not be instantiated",
-                     x);
+        }
+
+        @Override
+        public Provider<T> next() {
+            if (acc == null) {
+                return nextService();
+            } else {
+                PrivilegedAction<Provider<T>> action = new PrivilegedAction<>() {
+                    public Provider<T> run() { return nextService(); }
+                };
+                return AccessController.doPrivileged(action, acc);
             }
-            providers.add(p);
-            providerNames.add(cn);
-            return p;
         }
     }
 
     /**
-     * Lazily loads the available providers of this loader's service.
+     * Returns a new lookup iterator.
+     */
+    private Iterator<Provider<S>> newLookupIterator() {
+        assert layer == null || loader == null;
+        if (layer != null) {
+            return new LayerLookupIterator<>();
+        } else {
+            Iterator<Provider<S>> first = new ModuleServicesLookupIterator<>();
+            Iterator<Provider<S>> second = new LazyClassPathLookupIterator<>();
+            return new Iterator<Provider<S>>() {
+                @Override
+                public boolean hasNext() {
+                    return (first.hasNext() || second.hasNext());
+                }
+                @Override
+                public Provider<S> next() {
+                    if (first.hasNext()) {
+                        return first.next();
+                    } else if (second.hasNext()) {
+                        return second.next();
+                    } else {
+                        throw new NoSuchElementException();
+                    }
+                }
+            };
+        }
+    }
+
+    /**
+     * Lazily load and instantiate the available providers of this loader's
+     * service.
      *
      * <p> The iterator returned by this method first yields all of the
-     * elements of the provider cache, in instantiation order.  It then lazily
-     * loads and instantiates any remaining providers, adding each one to the
-     * cache in turn.
+     * elements of the provider cache, in the order that they were loaded.
+     * It then lazily loads and instantiates any remaining providers,
+     * adding each one to the cache in turn.
      *
      * <p> To achieve laziness the actual work of locating and instantiating
      * providers must be done by the iterator itself. Its {@link
      * java.util.Iterator#hasNext hasNext} and {@link java.util.Iterator#next
      * next} methods can therefore throw a {@link ServiceConfigurationError}
-     * if a provider class cannot be loaded, doesn't have the appropriate
-     * constructor, can't be assigned to the service type or if any other kind
-     * of exception or error is thrown as the next provider is located and
-     * instantiated. To write robust code it is only necessary to catch {@link
-     * ServiceConfigurationError} when using a service iterator.
+     * if a provider class cannot be loaded, doesn't have an appropriate static
+     * factory method or constructor, can't be assigned to the service type or
+     * if any other kind of exception or error is thrown as the next provider
+     * is located and instantiated. To write robust code it is only necessary
+     * to catch {@link ServiceConfigurationError} when using a service iterator.
      *
      * <p> If such an error is thrown then subsequent invocations of the
      * iterator will make a best effort to locate and instantiate the next
@@ -856,7 +1200,7 @@
      * preferable to throw an error rather than try to recover or, even worse,
      * fail silently.</blockquote>
      *
-     * <p> If this loader's provider cache is cleared by invoking the {@link
+     * <p> If this loader's provider caches are cleared by invoking the {@link
      * #reload() reload} method then existing iterators for this service
      * loader should be discarded.
      * The {@link java.util.Iterator#hasNext() hasNext} and {@link
@@ -868,16 +1212,16 @@
      * Invoking its {@link java.util.Iterator#remove() remove} method will
      * cause an {@link UnsupportedOperationException} to be thrown.
      *
-     * @implNote When adding providers to the cache, the {@link #iterator
-     * Iterator} processes resources in the order that the {@link
-     * java.lang.ClassLoader#getResources(java.lang.String)
-     * ClassLoader.getResources(String)} method finds the service configuration
-     * files.
-     *
      * @return  An iterator that lazily loads providers for this loader's
      *          service
      */
     public Iterator<S> iterator() {
+
+        // create lookup iterator if needed
+        if (lookupIterator1 == null) {
+            lookupIterator1 = newLookupIterator();
+        }
+
         return new Iterator<S>() {
 
             // record reload count
@@ -895,34 +1239,23 @@
                     throw new ConcurrentModificationException();
             }
 
+            @Override
             public boolean hasNext() {
                 checkReloadCount();
-                if (index < providers.size())
+                if (index < instantiatedProviders.size())
                     return true;
-
-                if (layerLookupIterator != null) {
-                    return layerLookupIterator.hasNext();
-                } else {
-                    return moduleServicesIterator.hasNext() ||
-                            lazyClassPathIterator.hasNext();
-                }
+                return lookupIterator1.hasNext();
             }
 
+            @Override
             public S next() {
                 checkReloadCount();
                 S next;
-                if (index < providers.size()) {
-                    next = providers.get(index);
+                if (index < instantiatedProviders.size()) {
+                    next = instantiatedProviders.get(index);
                 } else {
-                    if (layerLookupIterator != null) {
-                        next = layerLookupIterator.next();
-                    } else {
-                        if (moduleServicesIterator.hasNext()) {
-                            next = moduleServicesIterator.next();
-                        } else {
-                            next = lazyClassPathIterator.next();
-                        }
-                    }
+                    next = lookupIterator1.next().get();
+                    instantiatedProviders.add(next);
                 }
                 index++;
                 return next;
@@ -932,6 +1265,108 @@
     }
 
     /**
+     * Returns a stream that lazily loads the available providers of this
+     * loader's service. The stream elements are of type {@link Provider
+     * Provider}, the {@code Provider}'s {@link Provider#get() get} method
+     * must be invoked to get or instantiate the provider.
+     *
+     * <p> When processing the stream then providers that were previously
+     * loaded by stream operations are processed first, in load order. It then
+     * lazily loads any remaining providers. If a provider class cannot be
+     * loaded, can't be assigned to the service type, or some other error is
+     * thrown when locating the provider then it is wrapped with a {@code
+     * ServiceConfigurationError} and thrown by whatever method caused the
+     * provider to be loaded. </p>
+     *
+     * <p> If this loader's provider caches are cleared by invoking the {@link
+     * #reload() reload} method then existing streams for this service
+     * loader should be discarded. </p>
+     *
+     * <p> The following examples demonstrate usage. The first example
+     * creates a stream of providers, the second example is the same except
+     * that it sorts the providers by provider class name (and so locate all
+     * providers).
+     * <pre>{@code
+     *    Stream<CodecSet> providers = ServiceLoader.load(CodecSet.class)
+     *            .stream()
+     *            .map(Provider::get);
+     *
+     *    Stream<CodecSet> providers = ServiceLoader.load(CodecSet.class)
+     *            .stream()
+     *            .sorted(Comparator.comparing(p -> p.type().getName()))
+     *            .map(Provider::get);
+     * }</pre>
+     *
+     * @return  A stream that lazily loads providers for this loader's service
+     *
+     * @since 9
+     */
+    public Stream<Provider<S>> stream() {
+        // use cached providers as the source when all providers loaded
+        if (loadedAllProviders) {
+            return loadedProviders.stream();
+        }
+
+        // create lookup iterator if needed
+        if (lookupIterator2 == null) {
+            lookupIterator2 = newLookupIterator();
+        }
+
+        // use lookup iterator and cached providers as source
+        Spliterator<Provider<S>> s = new ProviderSpliterator<>(lookupIterator2);
+        return StreamSupport.stream(s, false);
+    }
+
+    private class ProviderSpliterator<T> implements Spliterator<Provider<T>> {
+        final int expectedReloadCount = ServiceLoader.this.reloadCount;
+        final Iterator<Provider<T>> iterator;
+        int index;
+
+        ProviderSpliterator(Iterator<Provider<T>> iterator) {
+            this.iterator = iterator;
+        }
+
+        @Override
+        public Spliterator<Provider<T>> trySplit() {
+            return null;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public boolean tryAdvance(Consumer<? super Provider<T>> action) {
+            if (ServiceLoader.this.reloadCount != expectedReloadCount)
+                throw new ConcurrentModificationException();
+            Provider<T> next = null;
+            if (index < loadedProviders.size()) {
+                next = (Provider<T>) loadedProviders.get(index++);
+            } else if (iterator.hasNext()) {
+                next = iterator.next();
+            } else {
+                loadedAllProviders = true;
+            }
+            if (next != null) {
+                action.accept(next);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int characteristics() {
+            // not IMMUTABLE as structural interference possible
+            // not NOTNULL so that the characteristics are a subset of the
+            // characteristics when all Providers have been located.
+            return Spliterator.ORDERED;
+        }
+
+        @Override
+        public long estimateSize() {
+            return Long.MAX_VALUE;
+        }
+    }
+
+    /**
      * Creates a new service loader for the given service type, class
      * loader, and caller.
      *
@@ -977,7 +1412,7 @@
      *
      * @throws ServiceConfigurationError
      *         if the service type is not accessible to the caller or the
-     *         caller is in a named module and its module descriptor does
+     *         caller is in an explicit module and its module descriptor does
      *         not declare that it uses {@code service}
      */
     @CallerSensitive
@@ -993,15 +1428,23 @@
      * context class loader}.
      *
      * <p> An invocation of this convenience method of the form
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>)</pre></blockquote>
+     * <pre>{@code
+     * ServiceLoader.load(service)
+     * }</pre>
      *
      * is equivalent to
      *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>,
-     *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
+     * <pre>{@code
+     * ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
+     * }</pre>
+     *
+     * @apiNote Service loader objects obtained with this method should not be
+     * cached VM-wide. For example, different applications in the same VM may
+     * have different thread context class loaders. A lookup by one application
+     * may locate a service provider that is only visible via its thread
+     * context class loader and so is not suitable to be located by the other
+     * application. Memory leaks can also arise. A thread local may be suited
+     * to some applications.
      *
      * @param  <S> the class of the service type
      *
@@ -1012,7 +1455,7 @@
      *
      * @throws ServiceConfigurationError
      *         if the service type is not accessible to the caller or the
-     *         caller is in a named module and its module descriptor does
+     *         caller is in an explicit module and its module descriptor does
      *         not declare that it uses {@code service}
      */
     @CallerSensitive
@@ -1027,9 +1470,9 @@
      *
      * <p> This convenience method is equivalent to: </p>
      *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>, <i>ClassLoader.getPlatformClassLoader())</i>
-     * </pre></blockquote>
+     * <pre>{@code
+     * ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
+     * }</pre>
      *
      * <p> This method is intended for use when only installed providers are
      * desired.  The resulting service will only find and load providers that
@@ -1045,18 +1488,13 @@
      *
      * @throws ServiceConfigurationError
      *         if the service type is not accessible to the caller or the
-     *         caller is in a named module and its module descriptor does
+     *         caller is in an explicit module and its module descriptor does
      *         not declare that it uses {@code service}
      */
     @CallerSensitive
     public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
-        ClassLoader cl = ClassLoader.getSystemClassLoader();
-        ClassLoader prev = null;
-        while (cl != null) {
-            prev = cl;
-            cl = cl.getParent();
-        }
-        return new ServiceLoader<>(Reflection.getCallerClass(), service, prev);
+        ClassLoader cl = ClassLoader.getPlatformClassLoader();
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
     }
 
     /**
@@ -1080,16 +1518,71 @@
      *
      * @throws ServiceConfigurationError
      *         if the service type is not accessible to the caller or the
-     *         caller is in a named module and its module descriptor does
+     *         caller is in an explicit module and its module descriptor does
      *         not declare that it uses {@code service}
      *
      * @since 9
      */
     @CallerSensitive
     public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) {
-        return new ServiceLoader<>(Reflection.getCallerClass(),
-                                   Objects.requireNonNull(layer),
-                                   Objects.requireNonNull(service));
+        return new ServiceLoader<>(Reflection.getCallerClass(), layer, service);
+    }
+
+    /**
+     * Load the first available provider of this loader's service. This
+     * convenience method is equivalent to invoking the {@link #iterator()
+     * iterator()} method and obtaining the first element. It therefore
+     * returns the first element from the provider cache if possible, it
+     * otherwise attempts to load and instantiate the first provider.
+     *
+     * <p> The following example loads the first available provider. If there
+     * are no providers deployed then it uses a default implementation.
+     * <pre>{@code
+     *    CodecSet provider =
+     *        ServiceLoader.load(CodecSet.class).findFirst().orElse(DEFAULT_CODECSET);
+     * }</pre>
+     * @return The first provider or empty {@code Optional} if no providers
+     *         are located
+     *
+     * @throws ServiceConfigurationError
+     *         If a provider class cannot be loaded, doesn't have the
+     *         appropriate static factory method or constructor, can't be
+     *         assigned to the service type, or if any other kind of exception
+     *         or error is thrown when locating or instantiating the provider.
+     *
+     * @since 9
+     */
+    public Optional<S> findFirst() {
+        Iterator<S> iterator = iterator();
+        if (iterator.hasNext()) {
+            return Optional.of(iterator.next());
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Clear this loader's provider cache so that all providers will be
+     * reloaded.
+     *
+     * <p> After invoking this method, subsequent invocations of the {@link
+     * #iterator() iterator} or {@link #stream() stream} methods will lazily
+     * look up providers (and instantiate in the case of {@code iterator})
+     * from scratch, just as is done by a newly-created loader.
+     *
+     * <p> This method is intended for use in situations in which new providers
+     * can be installed into a running Java virtual machine.
+     */
+    public void reload() {
+        lookupIterator1 = null;
+        instantiatedProviders.clear();
+
+        lookupIterator2 = null;
+        loadedProviders.clear();
+        loadedAllProviders = false;
+
+        // increment count to allow CME be thrown
+        reloadCount++;
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/util/Vector.java b/jdk/src/java.base/share/classes/java/util/Vector.java
index f6cdfbe..7c9d2cb 100644
--- a/jdk/src/java.base/share/classes/java/util/Vector.java
+++ b/jdk/src/java.base/share/classes/java/util/Vector.java
@@ -513,7 +513,7 @@
      * Returns the last component of the vector.
      *
      * @return  the last component of the vector, i.e., the component at index
-     *          <code>size()&nbsp;-&nbsp;1</code>.
+     *          {@code size() - 1}
      * @throws NoSuchElementException if this vector is empty
      */
     public synchronized E lastElement() {
@@ -675,10 +675,7 @@
      * method (which is part of the {@link List} interface).
      */
     public synchronized void removeAllElements() {
-        // Let gc do its work
-        for (int i = 0; i < elementCount; i++)
-            elementData[i] = null;
-
+        Arrays.fill(elementData, 0, elementCount, null);
         modCount++;
         elementCount = 0;
     }
@@ -693,7 +690,7 @@
     public synchronized Object clone() {
         try {
             @SuppressWarnings("unchecked")
-                Vector<E> v = (Vector<E>) super.clone();
+            Vector<E> v = (Vector<E>) super.clone();
             v.elementData = Arrays.copyOf(elementData, elementCount);
             v.modCount = 0;
             return v;
@@ -759,6 +756,11 @@
         return (E) elementData[index];
     }
 
+    @SuppressWarnings("unchecked")
+    static <E> E elementAt(Object[] es, int index) {
+        return (E) es[index];
+    }
+
     /**
      * Returns the element at the specified position in this Vector.
      *
@@ -855,10 +857,10 @@
      * Shifts any subsequent elements to the left (subtracts one from their
      * indices).  Returns the element that was removed from the Vector.
      *
-     * @throws ArrayIndexOutOfBoundsException if the index is out of range
-     *         ({@code index < 0 || index >= size()})
      * @param index the index of the element to be removed
      * @return element that was removed
+     * @throws ArrayIndexOutOfBoundsException if the index is out of range
+     *         ({@code index < 0 || index >= size()})
      * @since 1.2
      */
     public synchronized E remove(int index) {
@@ -949,8 +951,9 @@
      *         or if the specified collection is null
      * @since 1.2
      */
-    public synchronized boolean removeAll(Collection<?> c) {
-        return super.removeAll(c);
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
     }
 
     /**
@@ -972,8 +975,62 @@
      *         or if the specified collection is null
      * @since 1.2
      */
-    public synchronized boolean retainAll(Collection<?> c) {
-        return super.retainAll(c);
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    private synchronized boolean bulkRemove(Predicate<? super E> filter) {
+        int expectedModCount = modCount;
+        final Object[] es = elementData;
+        final int end = elementCount;
+        int i;
+        // Optimize for initial run of survivors
+        for (i = 0; i < end && !filter.test(elementAt(es, i)); i++)
+            ;
+        // Tolerate predicates that reentrantly access the collection for
+        // read (but writers still get CME), so traverse once to find
+        // elements to delete, a second pass to physically expunge.
+        if (i < end) {
+            final int beg = i;
+            final long[] deathRow = nBits(end - beg);
+            deathRow[0] = 1L;   // set bit 0
+            for (i = beg + 1; i < end; i++)
+                if (filter.test(elementAt(es, i)))
+                    setBit(deathRow, i - beg);
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            expectedModCount++;
+            modCount++;
+            int w = beg;
+            for (i = beg; i < end; i++)
+                if (isClear(deathRow, i - beg))
+                    es[w++] = es[i];
+            Arrays.fill(es, elementCount = w, end, null);
+            return true;
+        } else {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            return false;
+        }
     }
 
     /**
@@ -1095,15 +1152,12 @@
      * (If {@code toIndex==fromIndex}, this operation has no effect.)
      */
     protected synchronized void removeRange(int fromIndex, int toIndex) {
-        int numMoved = elementCount - toIndex;
-        System.arraycopy(elementData, toIndex, elementData, fromIndex,
-                         numMoved);
+        final Object[] es = elementData;
+        final int oldSize = elementCount;
+        System.arraycopy(es, toIndex, es, fromIndex, oldSize - toIndex);
 
-        // Let gc do its work
         modCount++;
-        int newElementCount = elementCount - (toIndex-fromIndex);
-        while (elementCount != newElementCount)
-            elementData[--elementCount] = null;
+        Arrays.fill(es, elementCount -= (toIndex - fromIndex), oldSize, null);
     }
 
     /**
@@ -1212,14 +1266,11 @@
                 if (i >= size) {
                     return;
                 }
-        @SuppressWarnings("unchecked")
-                final E[] elementData = (E[]) Vector.this.elementData;
-                if (i >= elementData.length) {
+                final Object[] es = elementData;
+                if (i >= es.length)
                     throw new ConcurrentModificationException();
-                }
-                while (i != size && modCount == expectedModCount) {
-                    action.accept(elementData[i++]);
-                }
+                while (i < size && modCount == expectedModCount)
+                    action.accept(elementAt(es, i++));
                 // update once at end of iteration to reduce heap write traffic
                 cursor = i;
                 lastRet = i - 1;
@@ -1290,73 +1341,24 @@
     public synchronized void forEach(Consumer<? super E> action) {
         Objects.requireNonNull(action);
         final int expectedModCount = modCount;
-        @SuppressWarnings("unchecked")
-        final E[] elementData = (E[]) this.elementData;
-        final int elementCount = this.elementCount;
-        for (int i=0; modCount == expectedModCount && i < elementCount; i++) {
-            action.accept(elementData[i]);
-        }
-        if (modCount != expectedModCount) {
-            throw new ConcurrentModificationException();
-        }
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public synchronized boolean removeIf(Predicate<? super E> filter) {
-        Objects.requireNonNull(filter);
-        // figure out which elements are to be removed
-        // any exception thrown from the filter predicate at this stage
-        // will leave the collection unmodified
-        int removeCount = 0;
+        final Object[] es = elementData;
         final int size = elementCount;
-        final BitSet removeSet = new BitSet(size);
-        final int expectedModCount = modCount;
-        for (int i=0; modCount == expectedModCount && i < size; i++) {
-            @SuppressWarnings("unchecked")
-            final E element = (E) elementData[i];
-            if (filter.test(element)) {
-                removeSet.set(i);
-                removeCount++;
-            }
-        }
-        if (modCount != expectedModCount) {
+        for (int i = 0; modCount == expectedModCount && i < size; i++)
+            action.accept(elementAt(es, i));
+        if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
-        }
-
-        // shift surviving elements left over the spaces left by removed elements
-        final boolean anyToRemove = removeCount > 0;
-        if (anyToRemove) {
-            final int newSize = size - removeCount;
-            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
-                i = removeSet.nextClearBit(i);
-                elementData[j] = elementData[i];
-            }
-            for (int k=newSize; k < size; k++) {
-                elementData[k] = null;  // Let gc do its work
-            }
-            elementCount = newSize;
-            if (modCount != expectedModCount) {
-                throw new ConcurrentModificationException();
-            }
-            modCount++;
-        }
-
-        return anyToRemove;
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public synchronized void replaceAll(UnaryOperator<E> operator) {
         Objects.requireNonNull(operator);
         final int expectedModCount = modCount;
+        final Object[] es = elementData;
         final int size = elementCount;
-        for (int i=0; modCount == expectedModCount && i < size; i++) {
-            elementData[i] = operator.apply((E) elementData[i]);
-        }
-        if (modCount != expectedModCount) {
+        for (int i = 0; modCount == expectedModCount && i < size; i++)
+            es[i] = operator.apply(elementAt(es, i));
+        if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
-        }
         modCount++;
     }
 
@@ -1365,9 +1367,8 @@
     public synchronized void sort(Comparator<? super E> c) {
         final int expectedModCount = modCount;
         Arrays.sort((E[]) elementData, 0, elementCount, c);
-        if (modCount != expectedModCount) {
+        if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
-        }
         modCount++;
     }
 
@@ -1397,7 +1398,7 @@
         private int fence; // -1 until used; then one past last index
         private int expectedModCount; // initialized when fence set
 
-        /** Create new spliterator covering the given  range */
+        /** Create new spliterator covering the given range */
         VectorSpliterator(Vector<E> list, Object[] array, int origin, int fence,
                           int expectedModCount) {
             this.list = list;
@@ -1410,7 +1411,7 @@
         private int getFence() { // initialize on first use
             int hi;
             if ((hi = fence) < 0) {
-                synchronized(list) {
+                synchronized (list) {
                     array = list.elementData;
                     expectedModCount = list.modCount;
                     hi = fence = list.elementCount;
@@ -1449,7 +1450,7 @@
                 throw new NullPointerException();
             if ((lst = list) != null) {
                 if ((hi = fence) < 0) {
-                    synchronized(lst) {
+                    synchronized (lst) {
                         expectedModCount = lst.modCount;
                         a = array = lst.elementData;
                         hi = fence = lst.elementCount;
@@ -1475,4 +1476,9 @@
             return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
         }
     }
+
+    void checkInvariants() {
+        // assert elementCount >= 0;
+        // assert elementCount == elementData.length || elementData[elementCount] == null;
+    }
 }
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
index 319a0bf..2688e17 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
@@ -46,6 +46,8 @@
 import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * A bounded {@linkplain BlockingQueue blocking queue} backed by an
@@ -85,6 +87,11 @@
 public class ArrayBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
 
+    /*
+     * Much of the implementation mechanics, especially the unusual
+     * nested loops, are shared and co-maintained with ArrayDeque.
+     */
+
     /**
      * Serialization ID. This class relies on default serialization
      * even for the items array, which is default-serialized, even if
@@ -129,10 +136,21 @@
     // Internal helper methods
 
     /**
-     * Circularly decrements array index i.
+     * Increments i, mod modulus.
+     * Precondition and postcondition: 0 <= i < modulus.
      */
-    final int dec(int i) {
-        return ((i == 0) ? items.length : i) - 1;
+    static final int inc(int i, int modulus) {
+        if (++i >= modulus) i = 0;
+        return i;
+    }
+
+    /**
+     * Decrements i, mod modulus.
+     * Precondition and postcondition: 0 <= i < modulus.
+     */
+    static final int dec(int i, int modulus) {
+        if (--i < 0) i = modulus - 1;
+        return i;
     }
 
     /**
@@ -144,14 +162,24 @@
     }
 
     /**
+     * Returns element at array index i.
+     * This is a slight abuse of generics, accepted by javac.
+     */
+    @SuppressWarnings("unchecked")
+    static <E> E itemAt(Object[] items, int i) {
+        return (E) items[i];
+    }
+
+    /**
      * Inserts element at current put position, advances, and signals.
      * Call only when holding lock.
      */
-    private void enqueue(E x) {
+    private void enqueue(E e) {
+        // assert lock.isHeldByCurrentThread();
         // assert lock.getHoldCount() == 1;
         // assert items[putIndex] == null;
         final Object[] items = this.items;
-        items[putIndex] = x;
+        items[putIndex] = e;
         if (++putIndex == items.length) putIndex = 0;
         count++;
         notEmpty.signal();
@@ -162,18 +190,19 @@
      * Call only when holding lock.
      */
     private E dequeue() {
+        // assert lock.isHeldByCurrentThread();
         // assert lock.getHoldCount() == 1;
         // assert items[takeIndex] != null;
         final Object[] items = this.items;
         @SuppressWarnings("unchecked")
-        E x = (E) items[takeIndex];
+        E e = (E) items[takeIndex];
         items[takeIndex] = null;
         if (++takeIndex == items.length) takeIndex = 0;
         count--;
         if (itrs != null)
             itrs.elementDequeued();
         notFull.signal();
-        return x;
+        return e;
     }
 
     /**
@@ -182,6 +211,7 @@
      * Call only when holding lock.
      */
     void removeAt(final int removeIndex) {
+        // assert lock.isHeldByCurrentThread();
         // assert lock.getHoldCount() == 1;
         // assert items[removeIndex] != null;
         // assert removeIndex >= 0 && removeIndex < items.length;
@@ -267,6 +297,7 @@
         final ReentrantLock lock = this.lock;
         lock.lock(); // Lock only for visibility, not mutual exclusion
         try {
+            final Object[] items = this.items;
             int i = 0;
             try {
                 for (E e : c)
@@ -481,15 +512,16 @@
         try {
             if (count > 0) {
                 final Object[] items = this.items;
-                final int putIndex = this.putIndex;
-                int i = takeIndex;
-                do {
-                    if (o.equals(items[i])) {
-                        removeAt(i);
-                        return true;
-                    }
-                    if (++i == items.length) i = 0;
-                } while (i != putIndex);
+                for (int i = takeIndex, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        if (o.equals(items[i])) {
+                            removeAt(i);
+                            return true;
+                        }
+                    if (to == end) break;
+                }
             }
             return false;
         } finally {
@@ -512,13 +544,14 @@
         try {
             if (count > 0) {
                 final Object[] items = this.items;
-                final int putIndex = this.putIndex;
-                int i = takeIndex;
-                do {
-                    if (o.equals(items[i]))
-                        return true;
-                    if (++i == items.length) i = 0;
-                } while (i != putIndex);
+                for (int i = takeIndex, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        if (o.equals(items[i]))
+                            return true;
+                    if (to == end) break;
+                }
             }
             return false;
         } finally {
@@ -625,15 +658,9 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int k = count;
-            if (k > 0) {
-                final Object[] items = this.items;
-                final int putIndex = this.putIndex;
-                int i = takeIndex;
-                do {
-                    items[i] = null;
-                    if (++i == items.length) i = 0;
-                } while (i != putIndex);
+            int k;
+            if ((k = count) > 0) {
+                circularClear(items, takeIndex, putIndex);
                 takeIndex = putIndex;
                 count = 0;
                 if (itrs != null)
@@ -647,6 +674,18 @@
     }
 
     /**
+     * Nulls out slots starting at array index i, upto index end.
+     * If i == end, the entire array is cleared!
+     */
+    private static void circularClear(Object[] items, int i, int end) {
+        for (int to = (i < end) ? end : items.length;
+             ; i = 0, to = end) {
+            Arrays.fill(items, i, to, null);
+            if (to == end) break;
+        }
+    }
+
+    /**
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
@@ -678,8 +717,8 @@
             try {
                 while (i < n) {
                     @SuppressWarnings("unchecked")
-                    E x = (E) items[take];
-                    c.add(x);
+                    E e = (E) items[take];
+                    c.add(e);
                     items[take] = null;
                     if (++take == items.length) take = 0;
                     i++;
@@ -808,7 +847,7 @@
          * there is known to be at least one iterator to collect
          */
         void doSomeSweeping(boolean tryHarder) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             // assert head != null;
             int probes = tryHarder ? LONG_SWEEP_PROBES : SHORT_SWEEP_PROBES;
             Node o, p;
@@ -864,7 +903,7 @@
          * Adds a new iterator to the linked list of tracked iterators.
          */
         void register(Itr itr) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             head = new Node(itr, head);
         }
 
@@ -874,7 +913,7 @@
          * Notifies all iterators, and expunges any that are now stale.
          */
         void takeIndexWrapped() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             cycles++;
             for (Node o = null, p = head; p != null;) {
                 final Itr it = p.get();
@@ -931,7 +970,7 @@
          * clears all weak refs, and unlinks the itrs datastructure.
          */
         void queueIsEmpty() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             for (Node p = head; p != null; p = p.next) {
                 Itr it = p.get();
                 if (it != null) {
@@ -947,7 +986,7 @@
          * Called whenever an element has been dequeued (at takeIndex).
          */
         void elementDequeued() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (count == 0)
                 queueIsEmpty();
             else if (takeIndex == 0)
@@ -1008,7 +1047,6 @@
         private static final int DETACHED = -3;
 
         Itr() {
-            // assert lock.getHoldCount() == 0;
             lastRet = NONE;
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
@@ -1041,12 +1079,12 @@
         }
 
         boolean isDetached() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             return prevTakeIndex < 0;
         }
 
         private int incCursor(int index) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (++index == items.length) index = 0;
             if (index == putIndex) index = NONE;
             return index;
@@ -1071,7 +1109,7 @@
          * operation on this iterator.  Call only from iterating thread.
          */
         private void incorporateDequeues() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             // assert itrs != null;
             // assert !isDetached();
             // assert count > 0;
@@ -1114,7 +1152,7 @@
          */
         private void detach() {
             // Switch to detached mode
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             // assert cursor == NONE;
             // assert nextIndex < 0;
             // assert lastRet < 0 || nextItem == null;
@@ -1134,7 +1172,6 @@
          * triggered by queue modifications.
          */
         public boolean hasNext() {
-            // assert lock.getHoldCount() == 0;
             if (nextItem != null)
                 return true;
             noNext();
@@ -1164,9 +1201,8 @@
         }
 
         public E next() {
-            // assert lock.getHoldCount() == 0;
-            final E x = nextItem;
-            if (x == null)
+            final E e = nextItem;
+            if (e == null)
                 throw new NoSuchElementException();
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
@@ -1188,13 +1224,43 @@
             } finally {
                 lock.unlock();
             }
-            return x;
+            return e;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+            lock.lock();
+            try {
+                final E e = nextItem;
+                if (e == null) return;
+                if (!isDetached())
+                    incorporateDequeues();
+                action.accept(e);
+                if (isDetached() || cursor < 0) return;
+                final Object[] items = ArrayBlockingQueue.this.items;
+                for (int i = cursor, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        action.accept(itemAt(items, i));
+                    if (to == end) break;
+                }
+            } finally {
+                // Calling forEachRemaining is a strong hint that this
+                // iteration is surely over; supporting remove() after
+                // forEachRemaining() is more trouble than it's worth
+                cursor = nextIndex = lastRet = NONE;
+                nextItem = lastItem = null;
+                detach();
+                lock.unlock();
+            }
         }
 
         public void remove() {
-            // assert lock.getHoldCount() == 0;
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
+            // assert lock.getHoldCount() == 1;
             try {
                 if (!isDetached())
                     incorporateDequeues(); // might update lastRet or detach
@@ -1232,7 +1298,7 @@
          * from next(), as promised by returning true from hasNext().
          */
         void shutdown() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             cursor = NONE;
             if (nextIndex >= 0)
                 nextIndex = REMOVED;
@@ -1260,7 +1326,7 @@
          * @return true if this iterator should be unlinked from itrs
          */
         boolean removedAt(int removedIndex) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (isDetached())
                 return true;
 
@@ -1285,7 +1351,7 @@
                 }
                 else if (x > removedDistance) {
                     // assert cursor != prevTakeIndex;
-                    this.cursor = cursor = dec(cursor);
+                    this.cursor = cursor = dec(cursor, len);
                 }
             }
             int lastRet = this.lastRet;
@@ -1294,7 +1360,7 @@
                 if (x == removedDistance)
                     this.lastRet = lastRet = REMOVED;
                 else if (x > removedDistance)
-                    this.lastRet = lastRet = dec(lastRet);
+                    this.lastRet = lastRet = dec(lastRet, len);
             }
             int nextIndex = this.nextIndex;
             if (nextIndex >= 0) {
@@ -1302,7 +1368,7 @@
                 if (x == removedDistance)
                     this.nextIndex = nextIndex = REMOVED;
                 else if (x > removedDistance)
-                    this.nextIndex = nextIndex = dec(nextIndex);
+                    this.nextIndex = nextIndex = dec(nextIndex, len);
             }
             if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
                 this.prevTakeIndex = DETACHED;
@@ -1317,7 +1383,7 @@
          * @return true if this iterator should be unlinked from itrs
          */
         boolean takeIndexWrapped() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (isDetached())
                 return true;
             if (itrs.cycles - prevCycles > 1) {
@@ -1366,4 +1432,170 @@
                     Spliterator.CONCURRENT));
     }
 
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            if (count > 0) {
+                final Object[] items = this.items;
+                for (int i = takeIndex, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        action.accept(itemAt(items, i));
+                    if (to == end) break;
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    /** Implementation of bulk remove methods. */
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            if (itrs == null) { // check for active iterators
+                if (count > 0) {
+                    final Object[] items = this.items;
+                    // Optimize for initial run of survivors
+                    for (int i = takeIndex, end = putIndex,
+                             to = (i < end) ? end : items.length;
+                         ; i = 0, to = end) {
+                        for (; i < to; i++)
+                            if (filter.test(itemAt(items, i)))
+                                return bulkRemoveModified(filter, i);
+                        if (to == end) break;
+                    }
+                }
+                return false;
+            }
+        } finally {
+            lock.unlock();
+        }
+        // Active iterators are too hairy!
+        // Punting (for now) to the slow n^2 algorithm ...
+        return super.removeIf(filter);
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    /**
+     * Returns circular distance from i to j, disambiguating i == j to
+     * items.length; never returns 0.
+     */
+    private int distanceNonEmpty(int i, int j) {
+        if ((j -= i) <= 0) j += items.length;
+        return j;
+    }
+
+    /**
+     * Helper for bulkRemove, in case of at least one deletion.
+     * Tolerate predicates that reentrantly access the collection for
+     * read (but not write), so traverse once to find elements to
+     * delete, a second pass to physically expunge.
+     *
+     * @param beg valid index of first element to be deleted
+     */
+    private boolean bulkRemoveModified(
+        Predicate<? super E> filter, final int beg) {
+        final Object[] es = items;
+        final int capacity = items.length;
+        final int end = putIndex;
+        final long[] deathRow = nBits(distanceNonEmpty(beg, putIndex));
+        deathRow[0] = 1L;   // set bit 0
+        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
+             ; i = 0, to = end, k -= capacity) {
+            for (; i < to; i++)
+                if (filter.test(itemAt(es, i)))
+                    setBit(deathRow, i - k);
+            if (to == end) break;
+        }
+        // a two-finger traversal, with hare i reading, tortoise w writing
+        int w = beg;
+        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
+             ; w = 0) { // w rejoins i on second leg
+            // In this loop, i and w are on the same leg, with i > w
+            for (; i < to; i++)
+                if (isClear(deathRow, i - k))
+                    es[w++] = es[i];
+            if (to == end) break;
+            // In this loop, w is on the first leg, i on the second
+            for (i = 0, to = end, k -= capacity; i < to && w < capacity; i++)
+                if (isClear(deathRow, i - k))
+                    es[w++] = es[i];
+            if (i >= to) {
+                if (w == capacity) w = 0; // "corner" case
+                break;
+            }
+        }
+        count -= distanceNonEmpty(w, end);
+        circularClear(es, putIndex = w, end);
+        return true;
+    }
+
+    /** debugging */
+    void checkInvariants() {
+        // meta-assertions
+        // assert lock.isHeldByCurrentThread();
+        try {
+            // Unlike ArrayDeque, we have a count field but no spare slot.
+            // We prefer ArrayDeque's strategy (and the names of its fields!),
+            // but our field layout is baked into the serial form, and so is
+            // too annoying to change.
+            //
+            // putIndex == takeIndex must be disambiguated by checking count.
+            int capacity = items.length;
+            // assert capacity > 0;
+            // assert takeIndex >= 0 && takeIndex < capacity;
+            // assert putIndex >= 0 && putIndex < capacity;
+            // assert count <= capacity;
+            // assert takeIndex == putIndex || items[takeIndex] != null;
+            // assert count == capacity || items[putIndex] == null;
+            // assert takeIndex == putIndex || items[dec(putIndex, capacity)] != null;
+        } catch (Throwable t) {
+            System.err.printf("takeIndex=%d putIndex=%d count=%d capacity=%d%n",
+                              takeIndex, putIndex, count, items.length);
+            System.err.printf("items=%s%n",
+                              Arrays.toString(items));
+            throw t;
+        }
+    }
+
 }
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java
index d855945..70b601a 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java
@@ -856,13 +856,9 @@
      * CompletableFuture, this method may return this stage itself.
      * Otherwise, invocation of this method may be equivalent in
      * effect to {@code thenApply(x -> x)}, but returning an instance
-     * of type {@code CompletableFuture}. A CompletionStage
-     * implementation that does not choose to interoperate with others
-     * may throw {@code UnsupportedOperationException}.
+     * of type {@code CompletableFuture}.
      *
      * @return the CompletableFuture
-     * @throws UnsupportedOperationException if this implementation
-     * does not interoperate with CompletableFuture
      */
     public CompletableFuture<T> toCompletableFuture();
 
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
index 7734a26..2ae29aa 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
@@ -1650,7 +1650,24 @@
      * Removes all of the mappings from this map.
      */
     public void clear() {
-        initialize();
+        for (;;) {
+            Node<K,V> b, n;
+            HeadIndex<K,V> h = head, d = (HeadIndex<K,V>)h.down;
+            if (d != null)
+                casHead(h, d);            // remove levels
+            else if ((b = h.node) != null && (n = b.next) != null) {
+                Node<K,V> f = n.next;     // remove values
+                if (n == b.next) {
+                    Object v = n.value;
+                    if (v == null)
+                        n.helpDelete(b, f);
+                    else if (n.casValue(v, null) && n.appendMarker(f))
+                        b.casNext(n, f);
+                }
+            }
+            else
+                break;
+        }
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
index 1f1b83c..47da30c 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
@@ -380,7 +380,7 @@
     // Positional Access Operations
 
     @SuppressWarnings("unchecked")
-    private E get(Object[] a, int index) {
+    static <E> E elementAt(Object[] a, int index) {
         return (E) a[index];
     }
 
@@ -394,7 +394,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E get(int index) {
-        return get(getArray(), index);
+        return elementAt(getArray(), index);
     }
 
     /**
@@ -406,7 +406,7 @@
     public E set(int index, E element) {
         synchronized (lock) {
             Object[] elements = getArray();
-            E oldValue = get(elements, index);
+            E oldValue = elementAt(elements, index);
 
             if (oldValue != element) {
                 int len = elements.length;
@@ -477,7 +477,7 @@
         synchronized (lock) {
             Object[] elements = getArray();
             int len = elements.length;
-            E oldValue = get(elements, index);
+            E oldValue = elementAt(elements, index);
             int numMoved = len - index - 1;
             if (numMoved == 0)
                 setArray(Arrays.copyOf(elements, len - 1));
@@ -644,34 +644,16 @@
      * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
-     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this list contains a null element and the
      *         specified collection does not permit null elements
-     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
     public boolean removeAll(Collection<?> c) {
-        if (c == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // temp array holds those elements we know we want to keep
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    Object element = elements[i];
-                    if (!c.contains(element))
-                        temp[newlen++] = element;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
-                    return true;
-                }
-            }
-            return false;
-        }
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
     }
 
     /**
@@ -683,34 +665,16 @@
      * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
-     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this list contains a null element and the
      *         specified collection does not permit null elements
-     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
     public boolean retainAll(Collection<?> c) {
-        if (c == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // temp array holds those elements we know we want to keep
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    Object element = elements[i];
-                    if (c.contains(element))
-                        temp[newlen++] = element;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
-                    return true;
-                }
-            }
-            return false;
-        }
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
     }
 
     /**
@@ -839,55 +803,90 @@
 
     public boolean removeIf(Predicate<? super E> filter) {
         if (filter == null) throw new NullPointerException();
+        return bulkRemove(filter);
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    private boolean bulkRemove(Predicate<? super E> filter) {
         synchronized (lock) {
-            final Object[] elements = getArray();
-            final int len = elements.length;
-            int i;
-            for (i = 0; i < len; i++) {
-                @SuppressWarnings("unchecked") E e = (E) elements[i];
-                if (filter.test(e)) {
-                    int newlen = i;
-                    final Object[] newElements = new Object[len - 1];
-                    System.arraycopy(elements, 0, newElements, 0, newlen);
-                    for (i++; i < len; i++) {
-                        @SuppressWarnings("unchecked") E x = (E) elements[i];
-                        if (!filter.test(x))
-                            newElements[newlen++] = x;
-                    }
-                    setArray((newlen == len - 1)
-                             ? newElements // one match => one copy
-                             : Arrays.copyOf(newElements, newlen));
-                    return true;
+            return bulkRemove(filter, 0, getArray().length);
+        }
+    }
+
+    boolean bulkRemove(Predicate<? super E> filter, int i, int end) {
+        // assert Thread.holdsLock(lock);
+        final Object[] es = getArray();
+        // Optimize for initial run of survivors
+        for (; i < end && !filter.test(elementAt(es, i)); i++)
+            ;
+        if (i < end) {
+            final int beg = i;
+            final long[] deathRow = nBits(end - beg);
+            int deleted = 1;
+            deathRow[0] = 1L;   // set bit 0
+            for (i = beg + 1; i < end; i++)
+                if (filter.test(elementAt(es, i))) {
+                    setBit(deathRow, i - beg);
+                    deleted++;
                 }
-            }
-            return false;       // zero matches => zero copies
+            // Did filter reentrantly modify the list?
+            if (es != getArray())
+                throw new ConcurrentModificationException();
+            final Object[] newElts = Arrays.copyOf(es, es.length - deleted);
+            int w = beg;
+            for (i = beg; i < end; i++)
+                if (isClear(deathRow, i - beg))
+                    newElts[w++] = es[i];
+            System.arraycopy(es, i, newElts, w, es.length - i);
+            setArray(newElts);
+            return true;
+        } else {
+            if (es != getArray())
+                throw new ConcurrentModificationException();
+            return false;
         }
     }
 
     public void replaceAll(UnaryOperator<E> operator) {
         if (operator == null) throw new NullPointerException();
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            Object[] newElements = Arrays.copyOf(elements, len);
-            for (int i = 0; i < len; ++i) {
-                @SuppressWarnings("unchecked") E e = (E) elements[i];
-                newElements[i] = operator.apply(e);
-            }
-            setArray(newElements);
+            replaceAll(operator, 0, getArray().length);
         }
     }
 
+    void replaceAll(UnaryOperator<E> operator, int i, int end) {
+        // assert Thread.holdsLock(lock);
+        final Object[] es = getArray().clone();
+        for (; i < end; i++)
+            es[i] = operator.apply(elementAt(es, i));
+        setArray(es);
+    }
+
     public void sort(Comparator<? super E> c) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            Object[] newElements = Arrays.copyOf(elements, elements.length);
-            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
-            Arrays.sort(es, c);
-            setArray(newElements);
+            sort(c, 0, getArray().length);
         }
     }
 
+    @SuppressWarnings("unchecked")
+    void sort(Comparator<? super E> c, int i, int end) {
+        // assert Thread.holdsLock(lock);
+        final Object[] es = getArray().clone();
+        Arrays.sort(es, i, end, (Comparator<Object>)c);
+        setArray(es);
+    }
+
     /**
      * Saves this list to a stream (that is, serializes it).
      *
@@ -1167,18 +1166,6 @@
 
     /**
      * Sublist for CopyOnWriteArrayList.
-     * This class extends AbstractList merely for convenience, to
-     * avoid having to define addAll, etc. This doesn't hurt, but
-     * is wasteful.  This class does not need or use modCount
-     * mechanics in AbstractList, but does need to check for
-     * concurrent modification using similar mechanics.  On each
-     * operation, the array that we expect the backing list to use
-     * is checked and updated.  Since we do this for all of the
-     * base operations invoked by those defined in AbstractList,
-     * all is well.  While inefficient, this is not worth
-     * improving.  The kinds of list operations inherited from
-     * AbstractList are already so slow on COW sublists that
-     * adding a bit more space/time doesn't seem even noticeable.
      */
     private static class COWSubList<E>
         extends AbstractList<E>
@@ -1206,6 +1193,14 @@
                 throw new ConcurrentModificationException();
         }
 
+        private Object[] getArrayChecked() {
+            // assert Thread.holdsLock(l.lock);
+            Object[] a = l.getArray();
+            if (a != expectedArray)
+                throw new ConcurrentModificationException();
+            return a;
+        }
+
         // only call this holding l's lock
         private void rangeCheck(int index) {
             // assert Thread.holdsLock(l.lock);
@@ -1217,7 +1212,7 @@
             synchronized (l.lock) {
                 rangeCheck(index);
                 checkForComodification();
-                E x = l.set(index+offset, element);
+                E x = l.set(offset + index, element);
                 expectedArray = l.getArray();
                 return x;
             }
@@ -1227,7 +1222,7 @@
             synchronized (l.lock) {
                 rangeCheck(index);
                 checkForComodification();
-                return l.get(index+offset);
+                return l.get(offset + index);
             }
         }
 
@@ -1238,22 +1233,41 @@
             }
         }
 
+        public boolean add(E element) {
+            synchronized (l.lock) {
+                checkForComodification();
+                l.add(offset + size, element);
+                expectedArray = l.getArray();
+                size++;
+            }
+            return true;
+        }
+
         public void add(int index, E element) {
             synchronized (l.lock) {
                 checkForComodification();
                 if (index < 0 || index > size)
                     throw new IndexOutOfBoundsException
                         (outOfBounds(index, size));
-                l.add(index+offset, element);
+                l.add(offset + index, element);
                 expectedArray = l.getArray();
                 size++;
             }
         }
 
+        public boolean addAll(Collection<? extends E> c) {
+            synchronized (l.lock) {
+                final Object[] oldArray = getArrayChecked();
+                boolean modified = l.addAll(offset + size, c);
+                size += (expectedArray = l.getArray()).length - oldArray.length;
+                return modified;
+            }
+        }
+
         public void clear() {
             synchronized (l.lock) {
                 checkForComodification();
-                l.removeRange(offset, offset+size);
+                l.removeRange(offset, offset + size);
                 expectedArray = l.getArray();
                 size = 0;
             }
@@ -1263,7 +1277,7 @@
             synchronized (l.lock) {
                 rangeCheck(index);
                 checkForComodification();
-                E result = l.remove(index+offset);
+                E result = l.remove(offset + index);
                 expectedArray = l.getArray();
                 size--;
                 return result;
@@ -1271,11 +1285,14 @@
         }
 
         public boolean remove(Object o) {
-            int index = indexOf(o);
-            if (index == -1)
-                return false;
-            remove(index);
-            return true;
+            synchronized (l.lock) {
+                checkForComodification();
+                int index = indexOf(o);
+                if (index == -1)
+                    return false;
+                remove(index);
+                return true;
+            }
         }
 
         public Iterator<E> iterator() {
@@ -1307,174 +1324,63 @@
 
         public void forEach(Consumer<? super E> action) {
             if (action == null) throw new NullPointerException();
-            int lo = offset;
-            int hi = offset + size;
-            Object[] a = expectedArray;
-            if (l.getArray() != a)
-                throw new ConcurrentModificationException();
-            if (lo < 0 || hi > a.length)
-                throw new IndexOutOfBoundsException();
-            for (int i = lo; i < hi; ++i) {
-                @SuppressWarnings("unchecked") E e = (E) a[i];
-                action.accept(e);
+            int i, end; final Object[] es;
+            synchronized (l.lock) {
+                es = getArrayChecked();
+                i = offset;
+                end = i + size;
             }
+            for (; i < end; i++)
+                action.accept(elementAt(es, i));
         }
 
         public void replaceAll(UnaryOperator<E> operator) {
             if (operator == null) throw new NullPointerException();
             synchronized (l.lock) {
-                int lo = offset;
-                int hi = offset + size;
-                Object[] elements = expectedArray;
-                if (l.getArray() != elements)
-                    throw new ConcurrentModificationException();
-                int len = elements.length;
-                if (lo < 0 || hi > len)
-                    throw new IndexOutOfBoundsException();
-                Object[] newElements = Arrays.copyOf(elements, len);
-                for (int i = lo; i < hi; ++i) {
-                    @SuppressWarnings("unchecked") E e = (E) elements[i];
-                    newElements[i] = operator.apply(e);
-                }
-                l.setArray(expectedArray = newElements);
+                checkForComodification();
+                l.replaceAll(operator, offset, offset + size);
+                expectedArray = l.getArray();
             }
         }
 
         public void sort(Comparator<? super E> c) {
             synchronized (l.lock) {
-                int lo = offset;
-                int hi = offset + size;
-                Object[] elements = expectedArray;
-                if (l.getArray() != elements)
-                    throw new ConcurrentModificationException();
-                int len = elements.length;
-                if (lo < 0 || hi > len)
-                    throw new IndexOutOfBoundsException();
-                Object[] newElements = Arrays.copyOf(elements, len);
-                @SuppressWarnings("unchecked") E[] es = (E[])newElements;
-                Arrays.sort(es, lo, hi, c);
-                l.setArray(expectedArray = newElements);
+                checkForComodification();
+                l.sort(c, offset, offset + size);
+                expectedArray = l.getArray();
             }
         }
 
         public boolean removeAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        Object element = elements[i];
-                        if (!c.contains(element))
-                            temp[newSize++] = element;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
-            }
-            return removed;
+            Objects.requireNonNull(c);
+            return bulkRemove(e -> c.contains(e));
         }
 
         public boolean retainAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        Object element = elements[i];
-                        if (c.contains(element))
-                            temp[newSize++] = element;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
-            }
-            return removed;
+            Objects.requireNonNull(c);
+            return bulkRemove(e -> !c.contains(e));
         }
 
         public boolean removeIf(Predicate<? super E> filter) {
-            if (filter == null) throw new NullPointerException();
-            boolean removed = false;
+            Objects.requireNonNull(filter);
+            return bulkRemove(filter);
+        }
+
+        private boolean bulkRemove(Predicate<? super E> filter) {
             synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        @SuppressWarnings("unchecked") E e = (E) elements[i];
-                        if (!filter.test(e))
-                            temp[newSize++] = e;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
+                final Object[] oldArray = getArrayChecked();
+                boolean modified = l.bulkRemove(filter, offset, offset + size);
+                size += (expectedArray = l.getArray()).length - oldArray.length;
+                return modified;
             }
-            return removed;
         }
 
         public Spliterator<E> spliterator() {
-            int lo = offset;
-            int hi = offset + size;
-            Object[] a = expectedArray;
-            if (l.getArray() != a)
-                throw new ConcurrentModificationException();
-            if (lo < 0 || hi > a.length)
-                throw new IndexOutOfBoundsException();
-            return Spliterators.spliterator
-                (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
+            synchronized (l.lock) {
+                return Spliterators.spliterator(
+                        getArrayChecked(), offset, offset + size,
+                        Spliterator.IMMUTABLE | Spliterator.ORDERED);
+            }
         }
 
     }
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
index beae1ca..97aae44 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
@@ -82,8 +82,7 @@
  *   public Solver(float[][] matrix) {
  *     data = matrix;
  *     N = matrix.length;
- *     Runnable barrierAction =
- *       new Runnable() { public void run() { mergeRows(...); }};
+ *     Runnable barrierAction = () -> mergeRows(...);
  *     barrier = new CyclicBarrier(N, barrierAction);
  *
  *     List<Thread> threads = new ArrayList<>(N);
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java b/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java
index a615705..378cacd 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java
@@ -87,14 +87,12 @@
  *     this.executor = executor;
  *   }
  *
- *   public synchronized void execute(final Runnable r) {
- *     tasks.add(new Runnable() {
- *       public void run() {
- *         try {
- *           r.run();
- *         } finally {
- *           scheduleNext();
- *         }
+ *   public synchronized void execute(Runnable r) {
+ *     tasks.add(() -> {
+ *       try {
+ *         r.run();
+ *       } finally {
+ *         scheduleNext();
  *       }
  *     });
  *     if (active == null) {
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java
index 9591d9b..7720883 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java
@@ -80,7 +80,7 @@
  *   List<Future<Result>> futures = new ArrayList<>(n);
  *   Result result = null;
  *   try {
- *     solvers.forEach((solver) -> futures.add(cs.submit(solver)));
+ *     solvers.forEach(solver -> futures.add(cs.submit(solver)));
  *     for (int i = n; i > 0; i--) {
  *       try {
  *         Result r = cs.take().get();
@@ -91,7 +91,7 @@
  *       } catch (ExecutionException ignore) {}
  *     }
  *   } finally {
- *     futures.forEach((future) -> future.cancel(true));
+ *     futures.forEach(future -> future.cancel(true));
  *   }
  *
  *   if (result != null)
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java b/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java
index cd91190..a31e3a1 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java
@@ -650,7 +650,7 @@
         public Thread newThread(final Runnable r) {
             return super.newThread(new Runnable() {
                 public void run() {
-                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    AccessController.doPrivileged(new PrivilegedAction<>() {
                         public Void run() {
                             Thread.currentThread().setContextClassLoader(ccl);
                             r.run();
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index 98524de..c549dbd 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -38,8 +38,10 @@
 import java.lang.Thread.UncaughtExceptionHandler;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.VarHandle;
+import java.security.AccessController;
 import java.security.AccessControlContext;
 import java.security.Permissions;
+import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -64,7 +66,8 @@
  * tasks are submitted to the pool from external clients.  Especially
  * when setting <em>asyncMode</em> to true in constructors, {@code
  * ForkJoinPool}s may also be appropriate for use with event-style
- * tasks that are never joined.
+ * tasks that are never joined. All worker threads are initialized
+ * with {@link Thread#isDaemon} set {@code true}.
  *
  * <p>A static {@link #commonPool()} is available and appropriate for
  * most applications. The common pool is used by any ForkJoinTask that
@@ -3224,10 +3227,9 @@
             new DefaultForkJoinWorkerThreadFactory();
         modifyThreadPermission = new RuntimePermission("modifyThread");
 
-        common = java.security.AccessController.doPrivileged
-            (new java.security.PrivilegedAction<ForkJoinPool>() {
-                    public ForkJoinPool run() {
-                        return new ForkJoinPool((byte)0); }});
+        common = AccessController.doPrivileged(new PrivilegedAction<>() {
+            public ForkJoinPool run() {
+                return new ForkJoinPool((byte)0); }});
 
         COMMON_PARALLELISM = Math.max(common.mode & SMASK, 1);
     }
@@ -3256,12 +3258,11 @@
         }
 
         public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
-            return java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
-                    public ForkJoinWorkerThread run() {
-                        return new ForkJoinWorkerThread.
-                            InnocuousForkJoinWorkerThread(pool);
-                    }}, INNOCUOUS_ACC);
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                public ForkJoinWorkerThread run() {
+                    return new ForkJoinWorkerThread.
+                        InnocuousForkJoinWorkerThread(pool);
+                }}, INNOCUOUS_ACC);
         }
     }
 
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
index bcd51f7..d9addf4 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
@@ -419,7 +419,7 @@
 
     /** Reference queue of stale exceptionally completed tasks. */
     private static final ReferenceQueue<ForkJoinTask<?>> exceptionTableRefQueue
-        = new ReferenceQueue<ForkJoinTask<?>>();
+        = new ReferenceQueue<>();
 
     /**
      * Key-value nodes for exception table.  The chained hash table
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Future.java b/jdk/src/java.base/share/classes/java/util/concurrent/Future.java
index 9bd05d6..6099c7c 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Future.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Future.java
@@ -50,8 +50,7 @@
  * declare types of the form {@code Future<?>} and
  * return {@code null} as a result of the underlying task.
  *
- * <p>
- * <b>Sample Usage</b> (Note that the following classes are all
+ * <p><b>Sample Usage</b> (Note that the following classes are all
  * made-up.)
  *
  * <pre> {@code
@@ -59,13 +58,9 @@
  * class App {
  *   ExecutorService executor = ...
  *   ArchiveSearcher searcher = ...
- *   void showSearch(final String target)
- *       throws InterruptedException {
- *     Future<String> future
- *       = executor.submit(new Callable<String>() {
- *         public String call() {
- *             return searcher.search(target);
- *         }});
+ *   void showSearch(String target) throws InterruptedException {
+ *     Callable<String> task = () -> searcher.search(target);
+ *     Future<String> future = executor.submit(task);
  *     displayOtherThings(); // do other things while searching
  *     try {
  *       displayText(future.get()); // use future
@@ -77,11 +72,7 @@
  * implements {@code Runnable}, and so may be executed by an {@code Executor}.
  * For example, the above construction with {@code submit} could be replaced by:
  * <pre> {@code
- * FutureTask<String> future =
- *   new FutureTask<>(new Callable<String>() {
- *     public String call() {
- *       return searcher.search(target);
- *   }});
+ * FutureTask<String> future = new FutureTask<>(task);
  * executor.execute(future);}</pre>
  *
  * <p>Memory consistency effects: Actions taken by the asynchronous computation
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
index c032dfe..708ab3d 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
@@ -1127,40 +1127,35 @@
     }
 
     /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class LBDSpliterator<E> implements Spliterator<E> {
+    private final class LBDSpliterator implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final LinkedBlockingDeque<E> queue;
         Node<E> current;    // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
         long est;           // size estimate
-        LBDSpliterator(LinkedBlockingDeque<E> queue) {
-            this.queue = queue;
-            this.est = queue.size();
-        }
+
+        LBDSpliterator() { est = size(); }
 
         public long estimateSize() { return est; }
 
         public Spliterator<E> trySplit() {
             Node<E> h;
-            final LinkedBlockingDeque<E> q = this.queue;
             int b = batch;
             int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
             if (!exhausted &&
-                ((h = current) != null || (h = q.first) != null) &&
-                h.next != null) {
+                (((h = current) != null && h != h.next)
+                 || (h = first) != null)
+                && h.next != null) {
                 Object[] a = new Object[n];
-                final ReentrantLock lock = q.lock;
+                final ReentrantLock lock = LinkedBlockingDeque.this.lock;
                 int i = 0;
                 Node<E> p = current;
                 lock.lock();
                 try {
-                    if (p != null || (p = q.first) != null) {
-                        do {
-                            if ((a[i] = p.item) != null)
-                                ++i;
-                        } while ((p = p.next) != null && i < n);
-                    }
+                    if (((p != null && p != p.next) || (p = first) != null)
+                        && p.item != null)
+                        for (; p != null && i < n; p = p.next)
+                            a[i++] = p.item;
                 } finally {
                     lock.unlock();
                 }
@@ -1183,64 +1178,55 @@
 
         public void forEachRemaining(Consumer<? super E> action) {
             if (action == null) throw new NullPointerException();
-            final LinkedBlockingDeque<E> q = this.queue;
-            final ReentrantLock lock = q.lock;
-            if (!exhausted) {
-                exhausted = true;
-                Node<E> p = current;
-                do {
-                    E e = null;
-                    lock.lock();
-                    try {
-                        if (p == null)
-                            p = q.first;
-                        while (p != null) {
-                            e = p.item;
-                            p = p.next;
-                            if (e != null)
-                                break;
-                        }
-                    } finally {
-                        lock.unlock();
-                    }
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
-        public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingDeque<E> q = this.queue;
-            final ReentrantLock lock = q.lock;
-            if (!exhausted) {
+            if (exhausted)
+                return;
+            exhausted = true;
+            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+            Node<E> p = current;
+            current = null;
+            do {
                 E e = null;
                 lock.lock();
                 try {
-                    if (current == null)
-                        current = q.first;
-                    while (current != null) {
-                        e = current.item;
-                        current = current.next;
-                        if (e != null)
-                            break;
+                    if ((p != null && p != p.next) || (p = first) != null) {
+                        e = p.item;
+                        p = p.next;
                     }
                 } finally {
                     lock.unlock();
                 }
-                if (current == null)
-                    exhausted = true;
-                if (e != null) {
+                if (e != null)
                     action.accept(e);
-                    return true;
+            } while (p != null);
+        }
+
+        public boolean tryAdvance(Consumer<? super E> action) {
+            if (action == null) throw new NullPointerException();
+            if (exhausted)
+                return false;
+            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+            Node<E> p = current;
+            E e = null;
+            lock.lock();
+            try {
+                if ((p != null && p != p.next) || (p = first) != null) {
+                    e = p.item;
+                    p = p.next;
                 }
+            } finally {
+                lock.unlock();
             }
-            return false;
+            exhausted = ((current = p) == null);
+            if (e == null)
+                return false;
+            action.accept(e);
+            return true;
         }
 
         public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
+            return (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT);
         }
     }
 
@@ -1261,7 +1247,7 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new LBDSpliterator<E>(this);
+        return new LBDSpliterator();
     }
 
     /**
@@ -1312,4 +1298,14 @@
         }
     }
 
+    void checkInvariants() {
+        // assert lock.isHeldByCurrentThread();
+        // Nodes may get self-linked or lose their item, but only
+        // after being unlinked and becoming unreachable from first.
+        for (Node<E> p = first; p != null; p = p.next) {
+            // assert p.next != p;
+            // assert p.item != null;
+        }
+    }
+
 }
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
index cb613e3..9433af6 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
@@ -95,8 +95,8 @@
      * *** Overview of Dual Queues with Slack ***
      *
      * Dual Queues, introduced by Scherer and Scott
-     * (http://www.cs.rice.edu/~wns1/papers/2004-DISC-DDS.pdf) are
-     * (linked) queues in which nodes may represent either data or
+     * (http://www.cs.rochester.edu/~scott/papers/2004_DISC_dual_DS.pdf)
+     * are (linked) queues in which nodes may represent either data or
      * requests.  When a thread tries to enqueue a data node, but
      * encounters a request node, it instead "matches" and removes it;
      * and vice versa for enqueuing requests. Blocking Dual Queues
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java
index 043c0b2..0a87239 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java
@@ -154,49 +154,46 @@
  * <p>A {@code Phaser} may be used instead of a {@code CountDownLatch}
  * to control a one-shot action serving a variable number of parties.
  * The typical idiom is for the method setting this up to first
- * register, then start the actions, then deregister, as in:
+ * register, then start all the actions, then deregister, as in:
  *
  * <pre> {@code
  * void runTasks(List<Runnable> tasks) {
- *   final Phaser phaser = new Phaser(1); // "1" to register self
+ *   Phaser startingGate = new Phaser(1); // "1" to register self
  *   // create and start threads
- *   for (final Runnable task : tasks) {
- *     phaser.register();
- *     new Thread() {
- *       public void run() {
- *         phaser.arriveAndAwaitAdvance(); // await all creation
- *         task.run();
- *       }
- *     }.start();
+ *   for (Runnable task : tasks) {
+ *     startingGate.register();
+ *     new Thread(() -> {
+ *       startingGate.arriveAndAwaitAdvance();
+ *       task.run();
+ *     }).start();
  *   }
  *
- *   // allow threads to start and deregister self
- *   phaser.arriveAndDeregister();
+ *   // deregister self to allow threads to proceed
+ *   startingGate.arriveAndDeregister();
  * }}</pre>
  *
  * <p>One way to cause a set of threads to repeatedly perform actions
  * for a given number of iterations is to override {@code onAdvance}:
  *
  * <pre> {@code
- * void startTasks(List<Runnable> tasks, final int iterations) {
- *   final Phaser phaser = new Phaser() {
+ * void startTasks(List<Runnable> tasks, int iterations) {
+ *   Phaser phaser = new Phaser() {
  *     protected boolean onAdvance(int phase, int registeredParties) {
  *       return phase >= iterations || registeredParties == 0;
  *     }
  *   };
  *   phaser.register();
- *   for (final Runnable task : tasks) {
+ *   for (Runnable task : tasks) {
  *     phaser.register();
- *     new Thread() {
- *       public void run() {
- *         do {
- *           task.run();
- *           phaser.arriveAndAwaitAdvance();
- *         } while (!phaser.isTerminated());
- *       }
- *     }.start();
+ *     new Thread(() -> {
+ *       do {
+ *         task.run();
+ *         phaser.arriveAndAwaitAdvance();
+ *       } while (!phaser.isTerminated());
+ *     }).start();
  *   }
- *   phaser.arriveAndDeregister(); // deregister self, don't wait
+ *   // allow threads to proceed; don't wait for them
+ *   phaser.arriveAndDeregister();
  * }}</pre>
  *
  * If the main task must later await termination, it
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
index 11d6339..64f03b6 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
@@ -933,8 +933,9 @@
         }
     }
 
-    // Similar to Collections.ArraySnapshotSpliterator but avoids
-    // commitment to toArray until needed
+    /**
+     * Immutable snapshot spliterator that binds to elements "late".
+     */
     static final class PBQSpliterator<E> implements Spliterator<E> {
         final PriorityBlockingQueue<E> queue;
         Object[] array;
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
index c32e2d1..2eae3a2 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
@@ -77,14 +77,11 @@
  *     Executors.newScheduledThreadPool(1);
  *
  *   public void beepForAnHour() {
- *     final Runnable beeper = new Runnable() {
- *       public void run() { System.out.println("beep"); }
- *     };
- *     final ScheduledFuture<?> beeperHandle =
+ *     Runnable beeper = () -> System.out.println("beep");
+ *     ScheduledFuture<?> beeperHandle =
  *       scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
- *     scheduler.schedule(new Runnable() {
- *       public void run() { beeperHandle.cancel(true); }
- *     }, 60 * 60, SECONDS);
+ *     Runnable canceller = () -> beeperHandle.cancel(true);
+ *     scheduler.schedule(canceller, 1, HOURS);
  *   }
  * }}</pre>
  *
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java
index f73c7fe..16f2566 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java
@@ -631,9 +631,12 @@
     }
 
     /**
-     * Acquires and returns all permits that are immediately available.
+     * Acquires and returns all permits that are immediately
+     * available, or if negative permits are available, releases them.
+     * Upon return, zero permits are available.
      *
-     * @return the number of permits acquired
+     * @return the number of permits acquired or, if negative, the
+     * number released
      */
     public int drainPermits() {
         return sync.drainPermits();
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
index e649307..cb1b4f2 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
@@ -197,9 +197,17 @@
         return r;
     }
 
-    // We must define this, but never use it.
+    /**
+     * Generates a pseudorandom number with the indicated number of
+     * low-order bits.  Because this class has no subclasses, this
+     * method cannot be invoked or overridden.
+     *
+     * @param  bits random bits
+     * @return the next pseudorandom value from this random number
+     *         generator's sequence
+     */
     protected int next(int bits) {
-        return (int)(mix64(nextSeed()) >>> (64 - bits));
+        return nextInt() >>> (32 - bits);
     }
 
     /**
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index c86f41d..55af35b 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -60,6 +60,10 @@
  * guarantee atomicity only with respect to other invocations of
  * {@code compareAndSet} and {@code set} on the same updater.
  *
+ * <p>Object arguments for parameters of type {@code T} that are not
+ * instances of the class passed to {@link #newUpdater} will result in
+ * a {@link ClassCastException} being thrown.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
@@ -105,8 +109,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean compareAndSet(T obj, int expect, int update);
 
@@ -125,8 +127,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean weakCompareAndSet(T obj, int expect, int update);
 
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index af39d8a..ff44467 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -60,6 +60,10 @@
  * guarantee atomicity only with respect to other invocations of
  * {@code compareAndSet} and {@code set} on the same updater.
  *
+ * <p>Object arguments for parameters of type {@code T} that are not
+ * instances of the class passed to {@link #newUpdater} will result in
+ * a {@link ClassCastException} being thrown.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
@@ -108,8 +112,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean compareAndSet(T obj, long expect, long update);
 
@@ -128,8 +130,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean weakCompareAndSet(T obj, long expect, long update);
 
@@ -510,8 +510,8 @@
 
         LockedUpdater(final Class<T> tclass, final String fieldName,
                       final Class<?> caller) {
-            Field field = null;
-            int modifiers = 0;
+            final Field field;
+            final int modifiers;
             try {
                 field = AccessController.doPrivileged(
                     new PrivilegedExceptionAction<Field>() {
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index faacb7f..2b75d56 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -77,6 +77,10 @@
  * guarantee atomicity only with respect to other invocations of
  * {@code compareAndSet} and {@code set} on the same updater.
  *
+ * <p>Object arguments for parameters of type {@code T} that are not
+ * instances of the class passed to {@link #newUpdater} will result in
+ * a {@link ClassCastException} being thrown.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
index b0ff27f..8390ff3 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
@@ -60,21 +60,9 @@
  *   }
  * }}</pre>
  *
- * <p>It is straightforward to define new utility functions that, like
- * {@code getAndIncrement}, apply a function to a value atomically.
- * For example, given some transformation
- * <pre> {@code long transform(long input)}</pre>
- *
- * write your utility method as follows:
- * <pre> {@code
- * long getAndTransform(AtomicLong var) {
- *   long prev, next;
- *   do {
- *     prev = var.get();
- *     next = transform(prev);
- *   } while (!var.compareAndSet(prev, next));
- *   return prev; // return next; for transformAndGet
- * }}</pre>
+ * <p>Arbitrary transformations of the contained value are provided both
+ * by low-level read-modify-write operations such as {@code compareAndSet}
+ * and by higher-level methods such as {@code getAndUpdate}.
  *
  * <p>These classes are not general purpose replacements for {@code
  * java.lang.Integer} and related classes.  They do <em>not</em>
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java
index 18fac82..583749b 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java
@@ -572,7 +572,7 @@
      * before acquiring the lock
      */
     @ReservedStackAccess
-        public long readLockInterruptibly() throws InterruptedException {
+    public long readLockInterruptibly() throws InterruptedException {
         long s, next;
         if (!Thread.interrupted()
             // bypass acquireRead on common uncontended case
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java b/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java
index 46b9398..0e992a2 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java
@@ -200,7 +200,7 @@
  * concurrent collection is thread-safe, but not governed by a
  * single exclusion lock.  In the particular case of
  * ConcurrentHashMap, it safely permits any number of
- * concurrent reads as well as a tunable number of concurrent
+ * concurrent reads as well as a large number of concurrent
  * writes.  "Synchronized" classes can be useful when you need
  * to prevent all access to a collection via a single lock, at
  * the expense of poorer scalability.  In other cases in which
diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java
index abf4b2f..ba072d7 100644
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java
@@ -48,8 +48,8 @@
  * processing multi-release jar files.  The {@code Manifest} can be used
  * to specify meta-information about the jar file and its entries.
  *
- * <p>A multi-release jar file is a jar file that contains
- * a manifest with a main attribute named "Multi-Release",
+ * <p><a name="multirelease">A multi-release jar file</a> is a jar file that
+ * contains a manifest with a main attribute named "Multi-Release",
  * a set of "base" entries, some of which are public classes with public
  * or protected methods that comprise the public interface of the jar file,
  * and a set of "versioned" entries contained in subdirectories of the
diff --git a/jdk/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java b/jdk/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java
index ba4cbdc..06b6c26 100644
--- a/jdk/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java
+++ b/jdk/src/java.base/share/classes/java/util/spi/AbstractResourceBundleProvider.java
@@ -25,37 +25,47 @@
 
 package java.util.spi;
 
+import jdk.internal.misc.JavaUtilResourceBundleAccess;
+import jdk.internal.misc.SharedSecrets;
+
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.UncheckedIOException;
 import java.lang.reflect.Module;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Locale;
+import java.util.PropertyResourceBundle;
 import java.util.ResourceBundle;
-import sun.util.locale.provider.ResourceBundleProviderSupport;
 import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
 
-
 /**
- * {@code AbstractResourceBundleProvider} is an abstract class for helping
- * implement the {@link ResourceBundleProvider} interface.
+ * {@code AbstractResourceBundleProvider} is an abstract class that provides
+ * the basic support for a provider implementation class for
+ * {@link ResourceBundleProvider}.
  *
  * <p>
- * Resource bundles can be packaged in a named module separated from
- * the <em>caller module</em> loading the resource bundle, i.e. the module
- * calling {@link ResourceBundle#getBundle(String)}.  For the caller module
- * to load a resource bundle "{@code com.example.app.MyResources}"
- * from another module and a service interface named
- * "{@code com.example.app.MyResourcesProvider}",
- * the <em>bundle provider module</em> can provide the implementation class
+ * Resource bundles can be packaged in one or more
+ * named modules, <em>bundle modules</em>.  The <em>consumer</em> of the
+ * resource bundle is the one calling {@link ResourceBundle#getBundle(String)}.
+ * In order for the consumer module to load a resource bundle
+ * "{@code com.example.app.MyResources}" provided by another module,
+ * it will use the {@linkplain java.util.ServiceLoader service loader}
+ * mechanism.  A service interface named "{@code com.example.app.MyResourcesProvider}"
+ * must be defined and a <em>bundle provider module</em> will provide an
+ * implementation class of "{@code com.example.app.MyResourcesProvider}"
  * as follows:
  *
  * <pre><code>
  * import com.example.app.MyResourcesProvider;
  * class MyResourcesProviderImpl extends AbstractResourceBundleProvider
  *     implements MyResourcesProvider
- * {</code>
- *     {@code @Override
+ * {
+ *     protected String toBundleName(String baseName, Locale locale) {
+ *         // return the bundle name per the naming of the resource bundle
+ *         :
+ *     }
+ *
  *     public ResourceBundle getBundle(String baseName, Locale locale) {
  *         // this module only provides bundles in french
  *         if (locale.equals(Locale.FRENCH)) {
@@ -63,7 +73,7 @@
  *         }
  *         return null;
  *     }
- * }}</pre>
+ * }</code></pre>
  *
  * @see <a href="../ResourceBundle.html#bundleprovider">
  *     Resource Bundles in Named Modules</a>
@@ -73,6 +83,9 @@
  * @since 9
  */
 public abstract class AbstractResourceBundleProvider implements ResourceBundleProvider {
+    private static final JavaUtilResourceBundleAccess RB_ACCESS =
+        SharedSecrets.getJavaUtilResourceBundleAccess();
+
     private static final String FORMAT_CLASS = "java.class";
     private static final String FORMAT_PROPERTIES = "java.properties";
 
@@ -112,7 +125,23 @@
 
     /**
      * Returns the bundle name for the given {@code baseName} and {@code
-     * locale}.  This method is called from the default implementation of the
+     * locale} that this provider provides.
+     *
+     * @apiNote
+     * A resource bundle provider may package its resource bundles in the
+     * same package as the base name of the resource bundle if the package
+     * is not split among other named modules.  If there are more than one
+     * bundle providers providing the resource bundle of a given base name,
+     * the resource bundles can be packaged with per-language grouping
+     * or per-region grouping to eliminate the split packages.
+     *
+     * <p>For example, if {@code baseName} is {@code "p.resources.Bundle"} then
+     * the resource bundle name of {@code "p.resources.Bundle"} of
+     * {@code Locale("ja",&nbsp;"",&nbsp;"XX")} and {@code Locale("en")}
+     * could be {@code "p.resources.ja.Bundle_ja_&thinsp;_XX"} and
+     * {@code p.resources.Bundle_en"} respectively
+     *
+     * <p> This method is called from the default implementation of the
      * {@link #getBundle(String, Locale)} method.
      *
      * @implNote The default implementation of this method is the same as the
@@ -126,27 +155,28 @@
      */
     protected String toBundleName(String baseName, Locale locale) {
         return ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT)
-                   .toBundleName(baseName, locale);
+            .toBundleName(baseName, locale);
     }
 
     /**
      * Returns a {@code ResourceBundle} for the given {@code baseName} and
-     * {@code locale}. This method calls the
-     * {@link #toBundleName(String, Locale) toBundleName} method to get the
-     * bundle name for the {@code baseName} and {@code locale}. The formats
-     * specified by the constructor will be searched to find the resource
-     * bundle.
+     * {@code locale}.
      *
      * @implNote
-     * The default implementation of this method will find the resource bundle
-     * local to the module of this provider.
+     * The default implementation of this method calls the
+     * {@link #toBundleName(String, Locale) toBundleName} method to get the
+     * bundle name for the {@code baseName} and {@code locale} and finds the
+     * resource bundle of the bundle name local in the module of this provider.
+     * It will only search the formats specified when this provider was
+     * constructed.
      *
      * @param baseName the base bundle name of the resource bundle, a fully
      *                 qualified class name.
      * @param locale the locale for which the resource bundle should be instantiated
-     * @return {@code ResourceBundle} of the given {@code baseName} and {@code locale},
-     *         or null if no resource bundle is found
-     * @throws NullPointerException if {@code baseName} or {@code locale} is null
+     * @return {@code ResourceBundle} of the given {@code baseName} and
+     *         {@code locale}, or {@code null} if no resource bundle is found
+     * @throws NullPointerException if {@code baseName} or {@code locale} is
+     *         {@code null}
      * @throws UncheckedIOException if any IO exception occurred during resource
      *         bundle loading
      */
@@ -159,13 +189,9 @@
         for (String format : formats) {
             try {
                 if (FORMAT_CLASS.equals(format)) {
-                    PrivilegedAction<ResourceBundle> pa = () ->
-                                    ResourceBundleProviderSupport
-                                         .loadResourceBundle(module, bundleName);
-                    bundle = AccessController.doPrivileged(pa, null, GET_CLASSLOADER_PERMISSION);
+                    bundle = loadResourceBundle(module, bundleName);
                 } else if (FORMAT_PROPERTIES.equals(format)) {
-                    bundle = ResourceBundleProviderSupport
-                                 .loadPropertyResourceBundle(module, bundleName);
+                    bundle = loadPropertyResourceBundle(module, bundleName);
                 }
                 if (bundle != null) {
                     break;
@@ -176,4 +202,61 @@
         }
         return bundle;
     }
+
+    /*
+     * Returns the ResourceBundle of .class format if found in the module
+     * of this provider.
+     */
+    private static ResourceBundle loadResourceBundle(Module module, String bundleName)
+    {
+        PrivilegedAction<Class<?>> pa = () -> Class.forName(module, bundleName);
+        Class<?> c = AccessController.doPrivileged(pa, null, GET_CLASSLOADER_PERMISSION);
+        if (c != null && ResourceBundle.class.isAssignableFrom(c)) {
+            @SuppressWarnings("unchecked")
+            Class<ResourceBundle> bundleClass = (Class<ResourceBundle>) c;
+            return RB_ACCESS.newResourceBundle(bundleClass);
+        }
+        return null;
+    }
+
+    /*
+     * Returns the ResourceBundle of .property format if found in the module
+     * of this provider.
+     */
+    private static ResourceBundle loadPropertyResourceBundle(Module module,
+                                                             String bundleName)
+        throws IOException
+    {
+        String resourceName = toResourceName(bundleName, "properties");
+        if (resourceName == null) {
+            return null;
+        }
+
+        PrivilegedAction<InputStream> pa = () -> {
+            try {
+                return module.getResourceAsStream(resourceName);
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
+            }
+        };
+        try (InputStream stream = AccessController.doPrivileged(pa)) {
+            if (stream != null) {
+                return new PropertyResourceBundle(stream);
+            } else {
+                return null;
+            }
+        } catch (UncheckedIOException e) {
+            throw e.getCause();
+        }
+    }
+
+    private static String toResourceName(String bundleName, String suffix) {
+        if (bundleName.contains("://")) {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder(bundleName.length() + 1 + suffix.length());
+        sb.append(bundleName.replace('.', '/')).append('.').append(suffix);
+        return sb.toString();
+    }
+
 }
diff --git a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java.template
similarity index 87%
rename from jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java
rename to jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java.template
index cc32f83..2705b4c 100644
--- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java
+++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java.template
@@ -23,10 +23,33 @@
  * questions.
  */
 
+/*
+ * README README README README README README README README README
+ *
+ * This file is the template for generating the JceSecurity.java source
+ * file.
+ *
+ * In the current jdk builds, this file is first preprocessed to replace
+ * @@JCE_DEFAULT_POLICY@ [sic] with "limited" or "unlimited" which is
+ * determined by the $(UNLIMTED_CRYPTO) make variable.  This variable is
+ * set by top-level configure script, using either
+ * --disable-unlimited-crypto or --enable-unlimited-crypto [default].
+ *
+ * Since this file is a generated source, incremental changes to
+ * this file require regenerating the source.  Compilation options:
+ *
+ *     (fewer dependencies/"faster" ones first)
+ *
+ * 1.  make JDK_FILTER=javax/crypto java.base-gensrc-only java.base-java-only
+ * 2.  make java.base-gensrc-only java.base-java-only
+ * 3.  make java.base-gensrc-only java.base-only
+ * 4.  make java.base-only
+ * 5.  make
+ */
+
 package javax.crypto;
 
 import java.util.*;
-import java.util.jar.*;
 import java.io.*;
 import java.net.URL;
 import java.nio.file.*;
@@ -36,6 +59,7 @@
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
+import sun.security.util.Debug;
 
 /**
  * This class instantiates implementations of JCE engine classes from
@@ -47,6 +71,9 @@
  */
 
 final class JceSecurity {
+  
+  	
+    private static final Debug debug = Debug.getInstance("jca");
 
     static final SecureRandom RANDOM = new SecureRandom();
 
@@ -251,10 +278,27 @@
         // directory entry, no pseudo-directories (".", "..", leading/trailing
         // path separators). normalize()/getParent() will help later.
         String cryptoPolicyProperty = Security.getProperty("crypto.policy");
+
+        /*
+         * In case no property is present, rather than fail catastrophically,
+         * we at least try for a "sane" value, which is what we were
+         * built with.  We first preprocess this file to plug in that
+         * value, then compile the result gensrc.
+         *
+         * Log the warning first.
+         */
+        if (cryptoPolicyProperty == null) {
+            cryptoPolicyProperty = "@@JCE_DEFAULT_POLICY@@";
+            if (debug != null) {
+                debug.println(
+                    "Security Property 'crypto.policy' not found: "
+                    + "using '" + cryptoPolicyProperty + "' as fallback");
+            }
+        }
+
         Path cpPath = Paths.get(cryptoPolicyProperty);
 
-        if ((cryptoPolicyProperty == null) ||
-                (cpPath.getNameCount() != 1) ||
+        if ((cpPath.getNameCount() != 1) ||
                 (cpPath.compareTo(cpPath.getFileName()) != 0)) {
             throw new SecurityException(
                 "Invalid policy directory name format: " +
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java
index 512a346..4aed7a6 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java
@@ -115,7 +115,7 @@
     private FileSystem newFileSystem(String targetHome, URI uri, Map<String, ?> env)
             throws IOException {
         Objects.requireNonNull(targetHome);
-        Path jrtfs = FileSystems.getDefault().getPath(targetHome, JRT_FS_JAR);
+        Path jrtfs = FileSystems.getDefault().getPath(targetHome, "lib", JRT_FS_JAR);
         if (Files.notExists(jrtfs)) {
             throw new IOException(jrtfs.toString() + " not exist");
         }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java
index 2da0d6e..c64ba6b 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java
@@ -113,12 +113,16 @@
         if (cs == null)
             return System.getProperty("java.home");
 
-        // assume loaded from $TARGETJDK/jrt-fs.jar
+        // assume loaded from $TARGETJDK/lib/jrt-fs.jar
         URL url = cs.getLocation();
         if (!url.getProtocol().equalsIgnoreCase("file"))
-            throw new RuntimeException(url + " loaded in unexpected way");
+            throw new InternalError(url + " loaded in unexpected way");
         try {
-            return Paths.get(url.toURI()).getParent().toString();
+            Path lib = Paths.get(url.toURI()).getParent();
+            if (!lib.getFileName().toString().equals("lib"))
+                throw new InternalError(url + " unexpected path");
+
+            return lib.getParent().toString();
         } catch (URISyntaxException e) {
             throw new InternalError(e);
         }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java
index 732248a..7885d8e 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java
@@ -71,8 +71,8 @@
     private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create();
 
     // ClassLoaderValue map for boot class loader
-    private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP =
-        new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP
+        = new ConcurrentHashMap<>();
 
     /**
      * Returns the unnamed module for the boot loader.
@@ -111,14 +111,27 @@
     }
 
     /**
-     * Returns a URL to a resource in a named module defined to the boot loader.
+     * Loads the Class object with the given name in the given module
+     * defined to the boot loader. Returns {@code null} if not found.
+     */
+    public static Class<?> loadClass(Module module, String name) {
+        Class<?> c = loadClassOrNull(name);
+        if (c != null && c.getModule() == module) {
+            return c;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns a URL to a resource in a module defined to the boot loader.
      */
     public static URL findResource(String mn, String name) throws IOException {
         return ClassLoaders.bootLoader().findResource(mn, name);
     }
 
     /**
-     * Returns an input stream to a resource in a named module defined to the
+     * Returns an input stream to a resource in a module defined to the
      * boot loader.
      */
     public static InputStream findResourceAsStream(String mn, String name)
@@ -128,9 +141,8 @@
     }
 
     /**
-     * Returns the URL to the given resource if the resource can be located
-     * on the boot class path. This method does not locate a resource in any
-     * of the named modules defined to the boot loader.
+     * Returns the URL to the given resource in any of the modules
+     * defined to the boot loader and the boot class path.
      */
     public static URL findResource(String name) {
         return ClassLoaders.bootLoader().findResource(name);
@@ -138,8 +150,7 @@
 
     /**
      * Returns an Iterator to iterate over the resources of the given name
-     * on the boot class path. This method does not locate resources in any
-     * of the named modules defined to the boot loader.
+     * in any of the modules defined to the boot loader.
      */
     public static Enumeration<URL> findResources(String name) throws IOException {
         return ClassLoaders.bootLoader().findResources(name);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
index e075598..ab052ec 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
@@ -29,8 +29,10 @@
 import java.io.FilePermission;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleReference;
 import java.lang.module.ModuleReader;
+import java.lang.ref.SoftReference;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
@@ -91,7 +93,7 @@
 {
     static {
         if (!ClassLoader.registerAsParallelCapable())
-            throw new InternalError();
+            throw new InternalError("Unable to register as parallel capable");
     }
 
     // parent ClassLoader
@@ -117,7 +119,7 @@
             if (mref.location().isPresent()) {
                 try {
                     url = mref.location().get().toURL();
-                } catch (MalformedURLException e) { }
+                } catch (MalformedURLException | IllegalArgumentException e) { }
             }
             this.loader = loader;
             this.mref = mref;
@@ -141,6 +143,9 @@
     // maps a module reference to a module reader
     private final Map<ModuleReference, ModuleReader> moduleToReader;
 
+    // cache of resource name -> list of URLs.
+    // used only for resources that are not in module packages
+    private volatile SoftReference<Map<String, List<URL>>> resourceCache;
 
     /**
      * Create a new instance.
@@ -161,6 +166,8 @@
      * the types in the module visible.
      */
     public void loadModule(ModuleReference mref) {
+        assert !VM.isModuleSystemInited();
+
         String mn = mref.descriptor().name();
         if (nameToModule.putIfAbsent(mn, mref) != null) {
             throw new InternalError(mn + " already defined to this loader");
@@ -195,32 +202,20 @@
      */
     @Override
     public URL findResource(String mn, String name) throws IOException {
-        ModuleReference mref = nameToModule.get(mn);
-        if (mref == null)
-            return null;   // not defined to this class loader
+        URL url = null;
 
-        URL url;
-
-        try {
-            url = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<URL>() {
-                    @Override
-                    public URL run() throws IOException {
-                        URI u = moduleReaderFor(mref).find(name).orElse(null);
-                        if (u != null) {
-                            try {
-                                return u.toURL();
-                            } catch (MalformedURLException e) { }
-                        }
-                        return null;
-                    }
-                });
-        } catch (PrivilegedActionException pae) {
-            throw (IOException) pae.getCause();
+        if (mn != null) {
+            // find in module
+            ModuleReference mref = nameToModule.get(mn);
+            if (mref != null) {
+                url = findResource(mref, name);
+            }
+        } else {
+            // find on class path
+            url = findResourceOnClassPath(name);
         }
 
-        // check access to the URL
-        return checkURL(url);
+        return checkURL(url);  // check access before returning
     }
 
     /**
@@ -232,69 +227,233 @@
     {
         // Need URL to resource when running with a security manager so that
         // the right permission check is done.
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-
+        if (System.getSecurityManager() != null || mn == null) {
             URL url = findResource(mn, name);
             return (url != null) ? url.openStream() : null;
-
-        } else {
-
-            ModuleReference mref = nameToModule.get(mn);
-            if (mref == null)
-                return null;   // not defined to this class loader
-
-            try {
-                return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<InputStream>() {
-                        @Override
-                        public InputStream run() throws IOException {
-                            return moduleReaderFor(mref).open(name).orElse(null);
-                        }
-                    });
-            } catch (PrivilegedActionException pae) {
-                throw (IOException) pae.getCause();
-            }
         }
-    }
 
-    /**
-     * Finds the resource with the given name on the class path of this class
-     * loader.
-     */
-    @Override
-    public URL findResource(String name) {
-        if (ucp != null) {
-            PrivilegedAction<URL> pa = () -> ucp.findResource(name, false);
-            URL url = AccessController.doPrivileged(pa);
-            return checkURL(url);
+        // find in module defined to this loader, no security manager
+        ModuleReference mref = nameToModule.get(mn);
+        if (mref != null) {
+            return moduleReaderFor(mref).open(name).orElse(null);
         } else {
             return null;
         }
     }
 
     /**
+     * Finds a resource with the given name in the modules defined to this
+     * class loader or its class path.
+     */
+    @Override
+    public URL findResource(String name) {
+        String pn = ResourceHelper.getPackageName(name);
+        LoadedModule module = packageToModule.get(pn);
+        if (module != null) {
+
+            // resource is in a package of a module defined to this loader
+            if (module.loader() == this
+                && (name.endsWith(".class") || isOpen(module.mref(), pn))) {
+                try {
+                    return findResource(module.name(), name); // checks URL
+                } catch (IOException ioe) {
+                    return null;
+                }
+            }
+
+        } else {
+
+            // not in a module package but may be in module defined to this loader
+            try {
+                List<URL> urls = findMiscResource(name);
+                if (!urls.isEmpty()) {
+                    URL url = urls.get(0);
+                    if (url != null) {
+                        return checkURL(url); // check access before returning
+                    }
+                }
+            } catch (IOException ioe) {
+                return null;
+            }
+
+        }
+
+        // search class path
+        URL url = findResourceOnClassPath(name);
+        return checkURL(url);
+    }
+
+    /**
      * Returns an enumeration of URL objects to all the resources with the
-     * given name on the class path of this class loader.
+     * given name in modules defined to this class loader or on the class
+     * path of this loader.
      */
     @Override
     public Enumeration<URL> findResources(String name) throws IOException {
-        if (ucp != null) {
-            List<URL> result = new ArrayList<>();
-            PrivilegedAction<Enumeration<URL>> pa = () -> ucp.findResources(name, false);
-            Enumeration<URL> e = AccessController.doPrivileged(pa);
-            while (e.hasMoreElements()) {
-                URL url = checkURL(e.nextElement());
+        List<URL> checked = new ArrayList<>();  // list of checked URLs
+
+        String pn = ResourceHelper.getPackageName(name);
+        LoadedModule module = packageToModule.get(pn);
+        if (module != null) {
+
+            // resource is in a package of a module defined to this loader
+            if (module.loader() == this
+                && (name.endsWith(".class") || isOpen(module.mref(), pn))) {
+                URL url = findResource(module.name(), name);  // checks URL
                 if (url != null) {
-                    result.add(url);
+                    checked.add(url);
                 }
             }
-            return Collections.enumeration(result); // checked URLs
+
         } else {
-            return Collections.emptyEnumeration();
+            // not in a package of a module defined to this loader
+            for (URL url : findMiscResource(name)) {
+                url = checkURL(url);
+                if (url != null) {
+                    checked.add(url);
+                }
+            }
+        }
+
+        // search class path
+        Enumeration<URL> e = findResourcesOnClassPath(name);
+        while (e.hasMoreElements()) {
+            URL url = checkURL(e.nextElement());
+            if (url != null) {
+                checked.add(url);
+            }
+        }
+
+        return Collections.enumeration(checked);
+    }
+
+    /**
+     * Returns the list of URLs to a "miscellaneous" resource in modules
+     * defined to this loader. A miscellaneous resource is not in a module
+     * package, e.g. META-INF/services/p.S.
+     *
+     * The cache used by this method avoids repeated searching of all modules.
+     */
+    private List<URL> findMiscResource(String name) throws IOException {
+        SoftReference<Map<String, List<URL>>> ref = this.resourceCache;
+        Map<String, List<URL>> map = (ref != null) ? ref.get() : null;
+        if (map != null) {
+            List<URL> urls = map.get(name);
+            if (urls != null)
+                return urls;
+        }
+
+        // search all modules for the resource
+        List<URL> urls;
+        try {
+            urls = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<>() {
+                    @Override
+                    public List<URL> run() throws IOException {
+                        List<URL> result = new ArrayList<>();
+                        for (ModuleReference mref : nameToModule.values()) {
+                            URI u = moduleReaderFor(mref).find(name).orElse(null);
+                            if (u != null) {
+                                try {
+                                    result.add(u.toURL());
+                                } catch (MalformedURLException |
+                                         IllegalArgumentException e) {
+                                }
+                            }
+                        }
+                        return result;
+                    }
+                });
+        } catch (PrivilegedActionException pae) {
+            throw (IOException) pae.getCause();
+        }
+
+        // only cache resources after all modules have been defined
+        if (VM.isModuleSystemInited()) {
+            if (map == null) {
+                map = new ConcurrentHashMap<>();
+                this.resourceCache = new SoftReference<>(map);
+            }
+            if (urls.isEmpty())
+                urls = Collections.emptyList();
+            map.putIfAbsent(name, urls);
+        }
+        return urls;
+    }
+
+    /**
+     * Returns the URL to a resource in a module or {@code null} if not found.
+     */
+    private URL findResource(ModuleReference mref, String name) throws IOException {
+        URI u;
+        if (System.getSecurityManager() == null) {
+            u = moduleReaderFor(mref).find(name).orElse(null);
+        } else {
+            try {
+                u = AccessController.doPrivileged(new PrivilegedExceptionAction<> () {
+                    @Override
+                    public URI run() throws IOException {
+                        return moduleReaderFor(mref).find(name).orElse(null);
+                    }
+                });
+            } catch (PrivilegedActionException pae) {
+                throw (IOException) pae.getCause();
+            }
+        }
+        if (u != null) {
+            try {
+                return u.toURL();
+            } catch (MalformedURLException | IllegalArgumentException e) { }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the URL to a resource in a module. Returns {@code null} if not found
+     * or an I/O error occurs.
+     */
+    private URL findResourceOrNull(ModuleReference mref, String name) {
+        try {
+            return findResource(mref, name);
+        } catch (IOException ignore) {
+            return null;
         }
     }
 
+    /**
+     * Returns a URL to a resource on the class path.
+     */
+    private URL findResourceOnClassPath(String name) {
+        if (ucp != null) {
+            if (System.getSecurityManager() == null) {
+                return ucp.findResource(name, false);
+            } else {
+                PrivilegedAction<URL> pa = () -> ucp.findResource(name, false);
+                return AccessController.doPrivileged(pa);
+            }
+        } else {
+            // no class path
+            return null;
+        }
+    }
+
+    /**
+     * Returns the URLs of all resources of the given name on the class path.
+     */
+    private Enumeration<URL> findResourcesOnClassPath(String name) {
+        if (ucp != null) {
+            if (System.getSecurityManager() == null) {
+                return ucp.findResources(name, false);
+            } else {
+                PrivilegedAction<Enumeration<URL>> pa;
+                pa = () -> ucp.findResources(name, false);
+                return AccessController.doPrivileged(pa);
+            }
+        } else {
+            // no class path
+            return Collections.emptyEnumeration();
+        }
+    }
 
     // -- finding/loading classes
 
@@ -335,24 +494,30 @@
     }
 
     /**
-     * Finds the class with the specified binary name in a given module.
-     * This method returns {@code null} if the class cannot be found.
+     * Finds the class with the specified binary name in a module.
+     * This method returns {@code null} if the class cannot be found
+     * or not defined in the specified module.
      */
     @Override
     protected Class<?> findClass(String mn, String cn) {
-        ModuleReference mref = nameToModule.get(mn);
-        if (mref == null)
-            return null;   // not defined to this class loader
+        if (mn != null) {
+            // find the candidate module for this class
+            LoadedModule loadedModule = findLoadedModule(mn, cn);
+            if (loadedModule == null) {
+                return null;
+            }
 
-        // find the candidate module for this class
-        LoadedModule loadedModule = findLoadedModule(cn);
-        if (loadedModule == null || !loadedModule.name().equals(mn)) {
-            return null;   // module name does not match
+            // attempt to load class in module defined to this loader
+            assert loadedModule.loader() == this;
+            return findClassInModuleOrNull(loadedModule, cn);
         }
 
-        // attempt to load class in module defined to this loader
-        assert loadedModule.loader() == this;
-        return findClassInModuleOrNull(loadedModule, cn);
+        // search class path
+        if (ucp != null) {
+            return findClassOnClassPathOrNull(cn);
+        }
+
+        return null;
     }
 
     /**
@@ -441,14 +606,33 @@
     }
 
     /**
+     * Find the candidate loaded module for the given class name
+     * in the named module.  Returns {@code null} if the named module
+     * is not defined to this class loader or does not contain
+     * the API package for the class.
+     */
+    private LoadedModule findLoadedModule(String mn, String cn) {
+        LoadedModule loadedModule = findLoadedModule(cn);
+        if (loadedModule != null && mn.equals(loadedModule.name())) {
+            return loadedModule;
+        } else {
+            return null;
+        }
+    }
+
+    /**
      * Finds the class with the specified binary name if in a module
      * defined to this ClassLoader.
      *
      * @return the resulting Class or {@code null} if not found
      */
     private Class<?> findClassInModuleOrNull(LoadedModule loadedModule, String cn) {
-        PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);
-        return AccessController.doPrivileged(pa);
+        if (System.getSecurityManager() == null) {
+            return defineClass(cn, loadedModule);
+        } else {
+            PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);
+            return AccessController.doPrivileged(pa);
+        }
     }
 
     /**
@@ -457,10 +641,21 @@
      * @return the resulting Class or {@code null} if not found
      */
     private Class<?> findClassOnClassPathOrNull(String cn) {
-        return AccessController.doPrivileged(
-            new PrivilegedAction<Class<?>>() {
+        String path = cn.replace('.', '/').concat(".class");
+        if (System.getSecurityManager() == null) {
+            Resource res = ucp.getResource(path, false);
+            if (res != null) {
+                try {
+                    return defineClass(cn, res);
+                } catch (IOException ioe) {
+                    // TBD on how I/O errors should be propagated
+                }
+            }
+            return null;
+        } else {
+            // avoid use of lambda here
+            PrivilegedAction<Class<?>> pa = new PrivilegedAction<>() {
                 public Class<?> run() {
-                    String path = cn.replace('.', '/').concat(".class");
                     Resource res = ucp.getResource(path, false);
                     if (res != null) {
                         try {
@@ -471,7 +666,9 @@
                     }
                     return null;
                 }
-            });
+            };
+            return AccessController.doPrivileged(pa);
+        }
     }
 
     /**
@@ -662,13 +859,13 @@
                 sealBase = url;
         }
         return definePackage(pn,
-                             specTitle,
-                             specVersion,
-                             specVendor,
-                             implTitle,
-                             implVersion,
-                             implVendor,
-                             sealBase);
+                specTitle,
+                specVersion,
+                specVendor,
+                implTitle,
+                implVersion,
+                implVendor,
+                sealBase);
     }
 
     /**
@@ -760,6 +957,27 @@
     };
 
     /**
+     * Returns true if the given module opens the given package
+     * unconditionally.
+     *
+     * @implNote This method currently iterates over each of the open
+     * packages. This will be replaced once the ModuleDescriptor.Opens
+     * API is updated.
+     */
+    private boolean isOpen(ModuleReference mref, String pn) {
+        ModuleDescriptor descriptor = mref.descriptor();
+        if (descriptor.isOpen())
+            return true;
+        for (ModuleDescriptor.Opens opens : descriptor.opens()) {
+            String source = opens.source();
+            if (!opens.isQualified() && source.equals(pn)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Checks access to the given URL. We use URLClassPath for consistent
      * checking with java.net.URLClassLoader.
      */
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
index 8b2e257..04285cc 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java
@@ -48,13 +48,19 @@
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.security.SecureClassLoader;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Stream;
 
+import jdk.internal.misc.SharedSecrets;
+
 
 /**
  * A class loader that loads classes and resources from a collection of
@@ -119,7 +125,7 @@
             if (mref.location().isPresent()) {
                 try {
                     url = mref.location().get().toURL();
-                } catch (MalformedURLException e) { }
+                } catch (MalformedURLException | IllegalArgumentException e) { }
             }
             this.mref = mref;
             this.url = url;
@@ -141,7 +147,7 @@
                   LoaderPool pool,
                   ClassLoader parent)
     {
-        super(parent);
+        super("Loader-" + resolvedModule.name(), parent);
 
         this.pool = pool;
         this.parent = parent;
@@ -200,12 +206,12 @@
      * @param cf the Configuration containing at least modules to be defined to
      *           this class loader
      *
-     * @param parentLayer the parent Layer
+     * @param parentLayers the parent Layers
      */
-    public Loader initRemotePackageMap(Configuration cf, Layer parentLayer) {
-
+    public Loader initRemotePackageMap(Configuration cf,
+                                       List<Layer> parentLayers)
+    {
         for (String name : nameToModule.keySet()) {
-
             ResolvedModule resolvedModule = cf.findModule(name).get();
             assert resolvedModule.configuration() == cf;
 
@@ -228,17 +234,15 @@
 
                 } else {
 
-                    // find the layer contains the module that is read
-                    Layer layer = parentLayer;
-                    while (layer != null) {
-                        if (layer.configuration() == other.configuration()) {
-                            break;
-                        }
-                        layer = layer.parent().orElse(null);
-                    }
-                    assert layer != null;
+                    // find the layer for the target module
+                    Layer layer = parentLayers.stream()
+                        .map(parent -> findLayer(parent, other.configuration()))
+                        .flatMap(Optional::stream)
+                        .findAny()
+                        .orElseThrow(() ->
+                            new InternalError("Unable to find parent layer"));
 
-                    // find the class loader for the module in the layer
+                    // find the class loader for the module
                     // For now we use the platform loader for modules defined to the
                     // boot loader
                     assert layer.findModule(mn).isPresent();
@@ -268,7 +272,6 @@
                             throw new IllegalArgumentException("Package "
                                 + pn + " cannot be imported from multiple loaders");
                         }
-
                     }
                 }
             }
@@ -279,6 +282,17 @@
     }
 
     /**
+     * Find the layer corresponding to the given configuration in the tree
+     * of layers rooted at the given parent.
+     */
+    private Optional<Layer> findLayer(Layer parent, Configuration cf) {
+        return SharedSecrets.getJavaLangReflectModuleAccess().layers(parent)
+                .filter(l -> l.configuration() == cf)
+                .findAny();
+    }
+
+
+    /**
      * Returns the loader pool that this loader is in or {@code null} if this
      * loader is not in a loader pool.
      */
@@ -296,12 +310,14 @@
      */
     @Override
     protected URL findResource(String mn, String name) throws IOException {
-        ModuleReference mref = nameToModule.get(mn);
+        ModuleReference mref = (mn != null) ? nameToModule.get(mn) : null;
         if (mref == null)
             return null;   // not defined to this class loader
 
+        // locate resource
+        URL url = null;
         try {
-            return AccessController.doPrivileged(
+            url = AccessController.doPrivileged(
                 new PrivilegedExceptionAction<URL>() {
                     @Override
                     public URL run() throws IOException {
@@ -309,16 +325,89 @@
                         if (ouri.isPresent()) {
                             try {
                                 return ouri.get().toURL();
-                            } catch (MalformedURLException e) { }
+                            } catch (MalformedURLException |
+                                     IllegalArgumentException e) { }
                         }
                         return null;
                     }
-                }, acc);
+                });
         } catch (PrivilegedActionException pae) {
             throw (IOException) pae.getCause();
-        } catch (SecurityException se) {
-            return null;
         }
+
+        // check access with permissions restricted by ACC
+        if (url != null && System.getSecurityManager() != null) {
+            try {
+                URL urlToCheck = url;
+                url = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<URL>() {
+                        @Override
+                        public URL run() throws IOException {
+                            return URLClassPath.checkURL(urlToCheck);
+                        }
+                    }, acc);
+            } catch (PrivilegedActionException pae) {
+                url = null;
+            }
+        }
+
+        return url;
+    }
+
+    @Override
+    public URL findResource(String name) {
+        URL url = null;
+        String pn = ResourceHelper.getPackageName(name);
+        LoadedModule module = localPackageToModule.get(pn);
+        if (module != null) {
+            if (name.endsWith(".class") || isOpen(module.mref(), pn)) {
+                try {
+                    url = findResource(module.name(), name);
+                } catch (IOException ioe) {
+                    // ignore
+                }
+            }
+        } else {
+            for (ModuleReference mref : nameToModule.values()) {
+                try {
+                    url = findResource(mref.descriptor().name(), name);
+                    if (url != null)
+                        break;
+                } catch (IOException ioe) {
+                    // ignore
+                }
+            }
+        }
+        return url;
+    }
+
+    @Override
+    public Enumeration<URL> findResources(String name) throws IOException {
+        List<URL> urls = new ArrayList<>();
+        String pn = ResourceHelper.getPackageName(name);
+        LoadedModule module = localPackageToModule.get(pn);
+        if (module != null) {
+            if (name.endsWith(".class") || isOpen(module.mref(), pn)) {
+                try {
+                    URL url = findResource(module.name(), name);
+                    if (url != null)
+                        urls.add(url);
+                } catch (IOException ioe) {
+                    // ignore
+                }
+            }
+        } else {
+            for (ModuleReference mref : nameToModule.values()) {
+                try {
+                    URL url = findResource(mref.descriptor().name(), name);
+                    if (url != null)
+                        urls.add(url);
+                } catch (IOException ioe) {
+                    // ignore
+                }
+            }
+        }
+        return Collections.enumeration(urls);
     }
 
 
@@ -544,4 +633,24 @@
         }
     }
 
+    /**
+     * Returns true if the given module opens the given package
+     * unconditionally.
+     *
+     * @implNote This method currently iterates over each of the open
+     * packages. This will be replaced once the ModuleDescriptor.Opens
+     * API is updated.
+     */
+    private boolean isOpen(ModuleReference mref, String pn) {
+        ModuleDescriptor descriptor = mref.descriptor();
+        if (descriptor.isOpen())
+            return true;
+        for (ModuleDescriptor.Opens opens : descriptor.opens()) {
+            String source = opens.source();
+            if (!opens.isQualified() && source.equals(pn)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/LoaderPool.java b/jdk/src/java.base/share/classes/jdk/internal/loader/LoaderPool.java
index a9bbc26..14b088c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/LoaderPool.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/LoaderPool.java
@@ -26,10 +26,10 @@
 package jdk.internal.loader;
 
 import java.lang.module.Configuration;
-import java.lang.module.ModuleReference;
 import java.lang.module.ResolvedModule;
 import java.lang.reflect.Layer;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.stream.Stream;
 
@@ -51,7 +51,7 @@
      * created with the given parent class loader as its parent.
      */
     public LoaderPool(Configuration cf,
-                      Layer parentLayer,
+                      List<Layer> parentLayers,
                       ClassLoader parentLoader)
     {
         Map<String, Loader> loaders = new HashMap<>();
@@ -63,7 +63,7 @@
         this.loaders = loaders;
 
         // complete the initialization
-        loaders.values().forEach(l -> l.initRemotePackageMap(cf, parentLayer));
+        loaders.values().forEach(l -> l.initRemotePackageMap(cf, parentLayers));
     }
 
 
diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/ResourceHelper.java b/jdk/src/java.base/share/classes/jdk/internal/loader/ResourceHelper.java
new file mode 100644
index 0000000..a9e0750
--- /dev/null
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ResourceHelper.java
@@ -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.  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.loader;
+
+import jdk.internal.module.Checks;
+
+/**
+ * Helper class for Class#getResource, Module#getResourceAsStream, and other
+ * methods that locate a resource in a module.
+ */
+public final class ResourceHelper {
+    private ResourceHelper() { }
+
+    /**
+     * Returns the <em>package name</em> for a resource.
+     */
+    public static String getPackageName(String name) {
+        int index = name.lastIndexOf('/');
+        if (index != -1) {
+            return name.substring(0, index).replace("/", ".");
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Returns true if the resource is a <em>simple resource</em> that can
+     * never be encapsulated. Resources ending in "{@code .class}" or where
+     * the package name is not a Java identifier are resources that can
+     * never be encapsulated.
+     */
+    public static boolean isSimpleResource(String name) {
+        int len = name.length();
+        if (len > 6 && name.endsWith(".class")) {
+            return true;
+        }
+        if (!Checks.isJavaIdentifier(getPackageName(name))) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
index f9699f7..6838111 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
@@ -29,6 +29,7 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Layer;
+import java.lang.reflect.Method;
 import java.lang.reflect.Module;
 import java.net.URL;
 import java.security.AccessControlContext;
@@ -36,12 +37,19 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Stream;
 
-import jdk.internal.module.ServicesCatalog;
 import jdk.internal.reflect.ConstantPool;
 import sun.reflect.annotation.AnnotationType;
 import sun.nio.ch.Interruptible;
 
 public interface JavaLangAccess {
+
+    /**
+     * Returns a {@code Method} object that reflects the specified public
+     * member method of the given class. Returns {@code null} if the
+     * method is not defined.
+     */
+    Method getMethodOrNull(Class<?> klass, String name, Class<?>... parameterTypes);
+
     /** Return the constant pool for a class. */
     ConstantPool getConstantPool(Class<?> klass);
 
@@ -136,17 +144,6 @@
     Layer getBootLayer();
 
     /**
-     * Returns the ServicesCatalog for the given class loader.
-     */
-    ServicesCatalog getServicesCatalog(ClassLoader cl);
-
-    /**
-     * Returns the ServicesCatalog for the given class loader, creating it
-     * if doesn't already exist.
-     */
-    ServicesCatalog createOrGetServicesCatalog(ClassLoader cl);
-
-    /**
      * Returns the ConcurrentHashMap used as a storage for ClassLoaderValue(s)
      * associated with the given class loader, creating it if it doesn't already exist.
      */
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
index d195792..d0b1c19 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java
@@ -27,24 +27,26 @@
 
 import java.io.PrintStream;
 import java.lang.module.Configuration;
-import jdk.internal.module.ModuleHashes;
-
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ModuleDescriptor.Version;
 import java.lang.module.ModuleFinder;
-import java.util.Collection;
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
 import java.net.URI;
 import java.nio.file.Path;
 import java.util.Map;
+import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Supplier;
 
+import jdk.internal.module.ModuleHashes;
+
 /**
  * Provides access to non-public methods in java.lang.module.
  */
@@ -52,28 +54,59 @@
 public interface JavaLangModuleAccess {
 
     /**
-     * Returns {@code ModuleDescriptor.Requires} of the given modifier
+     * Creates a builder for building a module with the given module name.
+     *
+     * @param strict
+     *        Indicates whether module names are checked or not
+     */
+    ModuleDescriptor.Builder newModuleBuilder(String mn, boolean strict);
+
+    /**
+     * Creates a builder for building an open module with the given module name.
+     *
+     * @param strict
+     *        Indicates whether module names are checked or not
+     */
+    ModuleDescriptor.Builder newOpenModuleBuilder(String mn, boolean strict);
+
+    /**
+     * Returns a {@code ModuleDescriptor.Requires} of the given modifiers
      * and module name.
      */
     Requires newRequires(Set<Requires.Modifier> ms, String mn);
 
     /**
      * Returns an unqualified {@code ModuleDescriptor.Exports}
-     * of the given package name.
+     * of the given modifiers and package name source.
      */
-    Exports newExports(String source);
+    Exports newExports(Set<Exports.Modifier> ms,
+                       String source);
 
     /**
      * Returns a qualified {@code ModuleDescriptor.Exports}
-     * of the given package name and targets.
+     * of the given modifiers, package name source and targets.
      */
-    Exports newExports(String source, Set<String> targets);
+    Exports newExports(Set<Exports.Modifier> ms,
+                       String source,
+                       Set<String> targets);
+
+    /**
+     * Returns an unqualified {@code ModuleDescriptor.Opens}
+     * of the given modifiers and package name source.
+     */
+    Opens newOpens(Set<Opens.Modifier> ms, String source);
+
+    /**
+     * Returns a qualified {@code ModuleDescriptor.Opens}
+     * of the given modifiers, package name source and targets.
+     */
+    Opens newOpens(Set<Opens.Modifier> ms, String source, Set<String> targets);
 
     /**
      * Returns a {@code ModuleDescriptor.Provides}
      * of the given service name and providers.
      */
-    Provides newProvides(String service, Set<String> providers);
+    Provides newProvides(String service, List<String> providers);
 
     /**
      * Returns a {@code ModuleDescriptor.Version} of the given version.
@@ -89,19 +122,22 @@
      * Returns a new {@code ModuleDescriptor} instance.
      */
     ModuleDescriptor newModuleDescriptor(String name,
+                                         boolean open,
                                          boolean automatic,
                                          boolean synthetic,
                                          Set<Requires> requires,
-                                         Set<String> uses,
                                          Set<Exports> exports,
-                                         Map<String, Provides> provides,
+                                         Set<Opens> opens,
+                                         Set<String> uses,
+                                         Set<Provides> provides,
                                          Version version,
                                          String mainClass,
                                          String osName,
                                          String osArch,
                                          String osVersion,
                                          Set<String> packages,
-                                         ModuleHashes hashes);
+                                         ModuleHashes hashes,
+                                         int hashCode);
 
     /**
      * Returns the object with the hashes of other modules
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
index 33c86cf..5577279 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java
@@ -29,6 +29,7 @@
 import java.lang.reflect.Layer;
 import java.lang.reflect.Module;
 import java.net.URI;
+import java.util.stream.Stream;
 
 import jdk.internal.module.ServicesCatalog;
 
@@ -71,16 +72,37 @@
     void addExports(Module m1, String pkg, Module m2);
 
     /**
+     * Updates module m1 to open a package to module m2. Opening the
+     * package does not result in a strong reference to m2 (m2 can be GC'ed).
+     */
+    void addOpens(Module m1, String pkg, Module m2);
+
+    /**
      * Updates a module m to export a package to all modules.
      */
     void addExportsToAll(Module m, String pkg);
 
     /**
+     * Updates a module m to open a package to all modules.
+     */
+    void addOpensToAll(Module m, String pkg);
+
+    /**
      * Updates a module m to export a package to all unnamed modules.
      */
     void addExportsToAllUnnamed(Module m, String pkg);
 
     /**
+     * Updates a module m to open a package to all unnamed modules.
+     */
+    void addOpensToAllUnnamed(Module m, String pkg);
+
+    /**
+     * Updates a module m to use a service.
+     */
+    void addUses(Module m, Class<?> service);
+
+    /**
      * Add a package to the given module.
      */
     void addPackage(Module m, String pkg);
@@ -90,4 +112,15 @@
      */
     ServicesCatalog getServicesCatalog(Layer layer);
 
+    /**
+     * Returns an ordered stream of layers. The first element is is the
+     * given layer, the remaining elements are its parents, in DFS order.
+     */
+    Stream<Layer> layers(Layer layer);
+
+    /**
+     * Returns a stream of the layers that have modules defined to the
+     * given class loader.
+     */
+    Stream<Layer> layers(ClassLoader loader);
 }
\ No newline at end of file
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilResourceBundleAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilResourceBundleAccess.java
index ab76a58..b137c3d 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilResourceBundleAccess.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilResourceBundleAccess.java
@@ -25,6 +25,7 @@
 
 package jdk.internal.misc;
 
+import java.lang.reflect.Module;
 import java.util.Locale;
 import java.util.ResourceBundle;
 
@@ -51,4 +52,16 @@
      * Sets the bundle's base name to the given name.
      */
     void setName(ResourceBundle bundle, String name);
+
+    /**
+     * Returns a {@code ResourceBundle} of the given baseName and locale
+     * loaded on behalf of the given module with no caller module
+     * access check.
+     */
+    ResourceBundle getBundle(String baseName, Locale locale, Module module);
+
+    /**
+     * Instantiates a {@code ResourceBundle} of the given bundle class.
+     */
+    ResourceBundle newResourceBundle(Class<? extends ResourceBundle> bundleClass);
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java
index d16ce84..36514cb 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java
@@ -26,6 +26,7 @@
 package jdk.internal.misc;
 
 import java.lang.module.ModuleDescriptor;
+import java.util.ResourceBundle;
 import java.util.jar.JarFile;
 import java.io.Console;
 import java.io.FileDescriptor;
@@ -294,6 +295,8 @@
     }
 
     public static JavaUtilResourceBundleAccess getJavaUtilResourceBundleAccess() {
+        if (javaUtilResourceBundleAccess == null)
+            unsafe.ensureClassInitialized(ResourceBundle.class);
         return javaUtilResourceBundleAccess;
     }
 
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
index fa4e752..961dd08 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,14 @@
 
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Version;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -40,7 +42,7 @@
 
 /**
  * This builder is optimized for reconstituting ModuleDescriptor
- * for installed modules.  The validation should be done at jlink time.
+ * for system modules.  The validation should be done at jlink time.
  *
  * 1. skip name validation
  * 2. ignores dependency hashes.
@@ -53,66 +55,137 @@
     private static final JavaLangModuleAccess jlma =
         SharedSecrets.getJavaLangModuleAccess();
 
-    private static final Set<Requires.Modifier> MANDATED =
-        Collections.singleton(Requires.Modifier.MANDATED);
-    private static final Set<Requires.Modifier> PUBLIC =
-        Collections.singleton(Requires.Modifier.PUBLIC);
-
     // Static cache of the most recently seen Version to cheaply deduplicate
     // most Version objects.  JDK modules have the same version.
     static Version cachedVersion;
 
+    /**
+     * Returns a {@link Requires} for a dependence on a module
+     * with the given (and possibly empty) set of modifiers.
+     */
+    public static Requires newRequires(Set<Requires.Modifier> mods,
+                                       String mn)
+    {
+        return jlma.newRequires(mods, mn);
+    }
+
+    /**
+     * Returns a {@link Exports} for a qualified export, with
+     * the given (and possibly empty) set of modifiers,
+     * to a set of target modules.
+     */
+    public static Exports newExports(Set<Exports.Modifier> ms,
+                                     String pn,
+                                     Set<String> targets) {
+        return jlma.newExports(ms, pn, targets);
+    }
+
+    /**
+     * Returns an {@link Opens} for an unqualified open with a given set of
+     * modifiers.
+     */
+    public static Opens newOpens(Set<Opens.Modifier> ms, String pn) {
+        return jlma.newOpens(ms, pn);
+    }
+
+    /**
+     * Returns an {@link Opens} for a qualified opens, with
+     * the given (and possibly empty) set of modifiers,
+     * to a set of target modules.
+     */
+    public static Opens newOpens(Set<Opens.Modifier> ms,
+                                 String pn,
+                                 Set<String> targets) {
+        return jlma.newOpens(ms, pn, targets);
+    }
+
+    /**
+     * Returns a {@link Exports} for an unqualified export with a given set
+     * of modifiers.
+     */
+    public static Exports newExports(Set<Exports.Modifier> ms, String pn) {
+        return jlma.newExports(ms, pn);
+    }
+
+    /**
+     * Returns a {@link Provides} for a service with a given list of
+     * implementation classes.
+     */
+    public static Provides newProvides(String st, List<String> pcs) {
+        return jlma.newProvides(st, pcs);
+    }
+
     final String name;
-    final Set<Requires> requires;
-    final Set<Exports> exports;
-    final Map<String, Provides> provides;
+    boolean open;
+    boolean automatic;
+    boolean synthetic;
+    Set<Requires> requires;
+    Set<Exports> exports;
+    Set<Opens> opens;
     Set<String> packages;
     Set<String> uses;
+    Set<Provides> provides;
     Version version;
     String mainClass;
     String osName;
     String osArch;
     String osVersion;
     String algorithm;
-    Map<String, String> hashes;
+    Map<String, byte[]> hashes;
 
-    Builder(String name, int reqs, int exports,
-            int provides, int packages) {
+    Builder(String name) {
         this.name = name;
-        this.requires = reqs > 0 ? new HashSet<>(reqs) : Collections.emptySet();
-        this.exports  = exports > 0 ? new HashSet<>(exports) : Collections.emptySet();
-        this.provides = provides > 0 ? new HashMap<>(provides) : Collections.emptyMap();
+        this.requires = Collections.emptySet();
+        this.exports = Collections.emptySet();
+        this.opens = Collections.emptySet();
+        this.provides = Collections.emptySet();
         this.uses = Collections.emptySet();
     }
 
-    /**
-     * Adds a module dependence with the given (and possibly empty) set
-     * of modifiers.
-     */
-    public Builder requires(Set<Requires.Modifier> mods, String mn) {
-        requires.add(jlma.newRequires(Collections.unmodifiableSet(mods), mn));
+    Builder open(boolean value) {
+        this.open = value;
+        return this;
+    }
+
+    Builder automatic(boolean value) {
+        this.automatic = value;
+        return this;
+    }
+
+    Builder synthetic(boolean value) {
+        this.synthetic = value;
         return this;
     }
 
     /**
-     * Adds a module dependence with an empty set of modifiers.
+     * Sets module exports.
      */
-    public Builder requires(String mn) {
-        requires.add(jlma.newRequires(Collections.emptySet(), mn));
+    public Builder exports(Exports[] exports) {
+        this.exports = Set.of(exports);
         return this;
     }
 
     /**
-     * Adds a module dependence with the given modifier.
+     * Sets module opens.
      */
-    public Builder requires(Requires.Modifier mod, String mn) {
-        if (mod == Requires.Modifier.MANDATED) {
-            requires.add(jlma.newRequires(MANDATED, mn));
-        } else if (mod == Requires.Modifier.PUBLIC) {
-            requires.add(jlma.newRequires(PUBLIC, mn));
-        } else {
-            requires.add(jlma.newRequires(Collections.singleton(mod), mn));
-        }
+    public Builder opens(Opens[] opens) {
+        this.opens = Set.of(opens);
+        return this;
+    }
+
+    /**
+     * Sets module requires.
+     */
+    public Builder requires(Requires[] requires) {
+        this.requires = Set.of(requires);
+        return this;
+    }
+
+    /**
+     * Adds a set of (possible empty) packages.
+     */
+    public Builder packages(Set<String> packages) {
+        this.packages = packages;
         return this;
     }
 
@@ -125,51 +198,10 @@
     }
 
     /**
-     * Adds an export to a set of target modules.
+     * Sets module provides.
      */
-    public Builder exports(String pn, Set<String> targets) {
-        exports.add(jlma.newExports(pn, targets));
-        return this;
-    }
-
-    /**
-     * Adds an export to a target module.
-     */
-    public Builder exports(String pn, String target) {
-        return exports(pn, Collections.singleton(target));
-    }
-
-    /**
-     * Adds an export.
-     */
-    public Builder exports(String pn) {
-        exports.add(jlma.newExports(pn));
-        return this;
-    }
-
-    /**
-     * Provides service {@code st} with implementations {@code pcs}.
-     */
-    public Builder provides(String st, Set<String> pcs) {
-        if (provides.containsKey(st))
-            throw new IllegalStateException("Providers of service "
-                    + st + " already declared");
-        provides.put(st, jlma.newProvides(st, pcs));
-        return this;
-    }
-
-    /**
-     * Provides service {@code st} with implementation {@code pc}.
-     */
-    public Builder provides(String st, String pc) {
-        return provides(st, Collections.singleton(pc));
-    }
-
-    /**
-     * Adds a set of (possible empty) packages.
-     */
-    public Builder packages(Set<String> packages) {
-        this.packages = packages;
+    public Builder provides(Provides[] provides) {
+        this.provides = Set.of(provides);
         return this;
     }
 
@@ -253,7 +285,7 @@
     /**
      * Sets the module hash for the given module name
      */
-    public Builder moduleHash(String mn, String hash) {
+    public Builder moduleHash(String mn, byte[] hash) {
         if (hashes == null)
             hashes = new HashMap<>();
 
@@ -264,18 +296,20 @@
     /**
      * Builds a {@code ModuleDescriptor} from the components.
      */
-    public ModuleDescriptor build() {
+    public ModuleDescriptor build(int hashCode) {
         assert name != null;
 
         ModuleHashes moduleHashes =
             hashes != null ? new ModuleHashes(algorithm, hashes) : null;
 
         return jlma.newModuleDescriptor(name,
-                                        false,    // automatic
-                                        false,    // assume not synthetic for now
+                                        open,
+                                        automatic,
+                                        synthetic,
                                         requires,
-                                        uses,
                                         exports,
+                                        opens,
+                                        uses,
                                         provides,
                                         version,
                                         mainClass,
@@ -283,6 +317,7 @@
                                         osArch,
                                         osVersion,
                                         packages,
-                                        moduleHashes);
+                                        moduleHashes,
+                                        hashCode);
     }
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java b/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
index 1738bfe..9f02048 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Checks.java
@@ -25,7 +25,6 @@
 
 package jdk.internal.module;
 
-
 public final class Checks {
 
     private Checks() { }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
index 73a44c8..908b137 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,17 +27,20 @@
 
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ModuleDescriptor.Version;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import jdk.internal.misc.JavaLangModuleAccess;
+import jdk.internal.misc.SharedSecrets;
 import jdk.internal.org.objectweb.asm.Attribute;
 import jdk.internal.org.objectweb.asm.ByteVector;
 import jdk.internal.org.objectweb.asm.ClassReader;
@@ -51,7 +54,7 @@
  * class file attributes in a module-info class file.
  */
 
-class ClassFileAttributes {
+public final class ClassFileAttributes {
 
     private ClassFileAttributes() { }
 
@@ -60,16 +63,18 @@
      *   // See lang-vm.html for details.
      * }
      */
-    static class ModuleAttribute extends Attribute {
+    public static class ModuleAttribute extends Attribute {
+        private static final JavaLangModuleAccess JLMA
+            = SharedSecrets.getJavaLangModuleAccess();
 
         private ModuleDescriptor descriptor;
 
-        ModuleAttribute(ModuleDescriptor descriptor) {
+        public ModuleAttribute(ModuleDescriptor descriptor) {
             super(MODULE);
             this.descriptor = descriptor;
         }
 
-        ModuleAttribute() {
+        public ModuleAttribute() {
             super(MODULE);
         }
 
@@ -81,27 +86,43 @@
                                  int codeOff,
                                  Label[] labels)
         {
-            ModuleDescriptor.Builder builder
-                = new ModuleDescriptor.Builder("xyzzy"); // Name never used
             ModuleAttribute attr = new ModuleAttribute();
 
+            // module_name
+            String mn = cr.readUTF8(off, buf).replace('/', '.');
+            off += 2;
+
+            // module_flags
+            int module_flags = cr.readUnsignedShort(off);
+            boolean open = ((module_flags & ACC_OPEN) != 0);
+            off += 2;
+
+            ModuleDescriptor.Builder builder;
+            if (open) {
+                builder = JLMA.newOpenModuleBuilder(mn, false);
+            } else {
+                builder = JLMA.newModuleBuilder(mn, false);
+            }
+
             // requires_count and requires[requires_count]
             int requires_count = cr.readUnsignedShort(off);
             off += 2;
             for (int i=0; i<requires_count; i++) {
-                String dn = cr.readUTF8(off, buf);
+                String dn = cr.readUTF8(off, buf).replace('/', '.');
                 int flags = cr.readUnsignedShort(off + 2);
-                Set<Modifier> mods;
+                Set<Requires.Modifier> mods;
                 if (flags == 0) {
                     mods = Collections.emptySet();
                 } else {
                     mods = new HashSet<>();
-                    if ((flags & ACC_PUBLIC) != 0)
-                        mods.add(Modifier.PUBLIC);
+                    if ((flags & ACC_TRANSITIVE) != 0)
+                        mods.add(Requires.Modifier.TRANSITIVE);
+                    if ((flags & ACC_STATIC_PHASE) != 0)
+                        mods.add(Requires.Modifier.STATIC);
                     if ((flags & ACC_SYNTHETIC) != 0)
-                        mods.add(Modifier.SYNTHETIC);
+                        mods.add(Requires.Modifier.SYNTHETIC);
                     if ((flags & ACC_MANDATED) != 0)
-                        mods.add(Modifier.MANDATED);
+                        mods.add(Requires.Modifier.MANDATED);
                 }
                 builder.requires(mods, dn);
                 off += 4;
@@ -113,18 +134,70 @@
             if (exports_count > 0) {
                 for (int i=0; i<exports_count; i++) {
                     String pkg = cr.readUTF8(off, buf).replace('/', '.');
-                    int exports_to_count = cr.readUnsignedShort(off+2);
-                    off += 4;
+                    off += 2;
+
+                    int flags = cr.readUnsignedShort(off);
+                    off += 2;
+                    Set<Exports.Modifier> mods;
+                    if (flags == 0) {
+                        mods = Collections.emptySet();
+                    } else {
+                        mods = new HashSet<>();
+                        if ((flags & ACC_SYNTHETIC) != 0)
+                            mods.add(Exports.Modifier.SYNTHETIC);
+                        if ((flags & ACC_MANDATED) != 0)
+                            mods.add(Exports.Modifier.MANDATED);
+                    }
+
+                    int exports_to_count = cr.readUnsignedShort(off);
+                    off += 2;
                     if (exports_to_count > 0) {
                         Set<String> targets = new HashSet<>();
                         for (int j=0; j<exports_to_count; j++) {
-                            String t = cr.readUTF8(off, buf);
+                            String t = cr.readUTF8(off, buf).replace('/', '.');
                             off += 2;
                             targets.add(t);
                         }
-                        builder.exports(pkg, targets);
+                        builder.exports(mods, pkg, targets);
                     } else {
-                        builder.exports(pkg);
+                        builder.exports(mods, pkg);
+                    }
+                }
+            }
+
+            // opens_count and opens[opens_count]
+            int open_count = cr.readUnsignedShort(off);
+            off += 2;
+            if (open_count > 0) {
+                for (int i=0; i<open_count; i++) {
+                    String pkg = cr.readUTF8(off, buf).replace('/', '.');
+                    off += 2;
+
+                    int flags = cr.readUnsignedShort(off);
+                    off += 2;
+                    Set<Opens.Modifier> mods;
+                    if (flags == 0) {
+                        mods = Collections.emptySet();
+                    } else {
+                        mods = new HashSet<>();
+                        if ((flags & ACC_SYNTHETIC) != 0)
+                            mods.add(Opens.Modifier.SYNTHETIC);
+                        if ((flags & ACC_MANDATED) != 0)
+                            mods.add(Opens.Modifier.MANDATED);
+                    }
+
+                    int opens_to_count = cr.readUnsignedShort(off);
+                    off += 2;
+                    if (opens_to_count > 0) {
+                        Set<String> targets = new HashSet<>();
+                        for (int j=0; j<opens_to_count; j++) {
+                            String t = cr.readUTF8(off, buf).replace('/', '.');
+                            off += 2;
+                            targets.add(t);
+                        }
+                        builder.opens(mods, pkg, targets);
+                    } else {
+                        builder.opens(mods, pkg);
                     }
                 }
             }
@@ -144,15 +217,19 @@
             int provides_count = cr.readUnsignedShort(off);
             off += 2;
             if (provides_count > 0) {
-                Map<String, Set<String>> provides = new HashMap<>();
                 for (int i=0; i<provides_count; i++) {
-                    String sn = cr.readClass(off, buf).replace('/', '.');
-                    String cn = cr.readClass(off + 2, buf).replace('/', '.');
-                    provides.computeIfAbsent(sn, k -> new LinkedHashSet<>()).add(cn);
-                    off += 4;
+                    String service = cr.readClass(off, buf).replace('/', '.');
+                    off += 2;
+                    int with_count = cr.readUnsignedShort(off);
+                    off += 2;
+                    List<String> providers = new ArrayList<>();
+                    for (int j=0; j<with_count; j++) {
+                        String cn = cr.readClass(off, buf).replace('/', '.');
+                        off += 2;
+                        providers.add(cn);
+                    }
+                    builder.provides(service, providers);
                 }
-                provides.entrySet().forEach(e -> builder.provides(e.getKey(),
-                                                                  e.getValue()));
             }
 
             attr.descriptor = builder.build();
@@ -169,6 +246,19 @@
             assert descriptor != null;
             ByteVector attr = new ByteVector();
 
+            // module_name
+            String mn = descriptor.name();
+            int module_name_index = cw.newUTF8(mn.replace('.', '/'));
+            attr.putShort(module_name_index);
+
+            // module_flags
+            int module_flags = 0;
+            if (descriptor.isOpen())
+                module_flags |= ACC_OPEN;
+            if (descriptor.isSynthetic())
+                module_flags |= ACC_SYNTHETIC;
+            attr.putShort(module_flags);
+
             // requires_count
             attr.putShort(descriptor.requires().size());
 
@@ -176,32 +266,61 @@
             for (Requires md : descriptor.requires()) {
                 String dn = md.name();
                 int flags = 0;
-                if (md.modifiers().contains(Modifier.PUBLIC))
-                    flags |= ACC_PUBLIC;
-                if (md.modifiers().contains(Modifier.SYNTHETIC))
+                if (md.modifiers().contains(Requires.Modifier.TRANSITIVE))
+                    flags |= ACC_TRANSITIVE;
+                if (md.modifiers().contains(Requires.Modifier.STATIC))
+                    flags |= ACC_STATIC_PHASE;
+                if (md.modifiers().contains(Requires.Modifier.SYNTHETIC))
                     flags |= ACC_SYNTHETIC;
-                if (md.modifiers().contains(Modifier.MANDATED))
+                if (md.modifiers().contains(Requires.Modifier.MANDATED))
                     flags |= ACC_MANDATED;
-                int index = cw.newUTF8(dn);
+                int index = cw.newUTF8(dn.replace('.', '/'));
                 attr.putShort(index);
                 attr.putShort(flags);
             }
 
             // exports_count and exports[exports_count];
-            if (descriptor.exports().isEmpty()) {
-                attr.putShort(0);
-            } else {
-                attr.putShort(descriptor.exports().size());
-                for (Exports e : descriptor.exports()) {
-                    String pkg = e.source().replace('.', '/');
-                    attr.putShort(cw.newUTF8(pkg));
-                    if (e.isQualified()) {
-                        Set<String> ts = e.targets();
-                        attr.putShort(ts.size());
-                        ts.forEach(t -> attr.putShort(cw.newUTF8(t)));
-                    } else {
-                        attr.putShort(0);
-                    }
+            attr.putShort(descriptor.exports().size());
+            for (Exports e : descriptor.exports()) {
+                String pkg = e.source().replace('.', '/');
+                attr.putShort(cw.newUTF8(pkg));
+
+                int flags = 0;
+                if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
+                    flags |= ACC_SYNTHETIC;
+                if (e.modifiers().contains(Exports.Modifier.MANDATED))
+                    flags |= ACC_MANDATED;
+                attr.putShort(flags);
+
+                if (e.isQualified()) {
+                    Set<String> ts = e.targets();
+                    attr.putShort(ts.size());
+                    ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+                } else {
+                    attr.putShort(0);
+                }
+            }
+
+
+            // opens_counts and opens[opens_counts]
+            attr.putShort(descriptor.opens().size());
+            for (Opens obj : descriptor.opens()) {
+                String pkg = obj.source().replace('.', '/');
+                attr.putShort(cw.newUTF8(pkg));
+
+                int flags = 0;
+                if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
+                    flags |= ACC_SYNTHETIC;
+                if (obj.modifiers().contains(Opens.Modifier.MANDATED))
+                    flags |= ACC_MANDATED;
+                attr.putShort(flags);
+
+                if (obj.isQualified()) {
+                    Set<String> ts = obj.targets();
+                    attr.putShort(ts.size());
+                    ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+                } else {
+                    attr.putShort(0);
                 }
             }
 
@@ -221,14 +340,13 @@
             if (descriptor.provides().isEmpty()) {
                 attr.putShort(0);
             } else {
-                int count = descriptor.provides().values()
-                    .stream().mapToInt(ps -> ps.providers().size()).sum();
-                attr.putShort(count);
-                for (Provides p : descriptor.provides().values()) {
+                attr.putShort(descriptor.provides().size());
+                for (Provides p : descriptor.provides()) {
                     String service = p.service().replace('.', '/');
-                    int index = cw.newClass(service);
+                    attr.putShort(cw.newClass(service));
+                    int with_count = p.providers().size();
+                    attr.putShort(with_count);
                     for (String provider : p.providers()) {
-                        attr.putShort(index);
                         attr.putShort(cw.newClass(provider.replace('.', '/')));
                     }
                 }
@@ -239,44 +357,13 @@
     }
 
     /**
-     * Synthetic attribute.
-     */
-    static class SyntheticAttribute extends Attribute {
-        SyntheticAttribute() {
-            super(SYNTHETIC);
-        }
-
-        @Override
-        protected Attribute read(ClassReader cr,
-                                 int off,
-                                 int len,
-                                 char[] buf,
-                                 int codeOff,
-                                 Label[] labels)
-        {
-            return new SyntheticAttribute();
-        }
-
-        @Override
-        protected ByteVector write(ClassWriter cw,
-                                   byte[] code,
-                                   int len,
-                                   int maxStack,
-                                   int maxLocals)
-        {
-            ByteVector attr = new ByteVector();
-            return attr;
-        }
-    }
-
-    /**
-     * ConcealedPackages attribute.
+     * ModulePackages attribute.
      *
      * <pre> {@code
      *
-     * ConcealedPackages_attribute {
+     * ModulePackages_attribute {
      *   // index to CONSTANT_utf8_info structure in constant pool representing
-     *   // the string "ConcealedPackages"
+     *   // the string "ModulePackages"
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
@@ -288,15 +375,15 @@
      *
      * }</pre>
      */
-    static class ConcealedPackagesAttribute extends Attribute {
+    public static class ModulePackagesAttribute extends Attribute {
         private final Set<String> packages;
 
-        ConcealedPackagesAttribute(Set<String> packages) {
-            super(CONCEALED_PACKAGES);
+        public ModulePackagesAttribute(Set<String> packages) {
+            super(MODULE_PACKAGES);
             this.packages = packages;
         }
 
-        ConcealedPackagesAttribute() {
+        public ModulePackagesAttribute() {
             this(null);
         }
 
@@ -320,7 +407,7 @@
                 off += 2;
             }
 
-            return new ConcealedPackagesAttribute(packages);
+            return new ModulePackagesAttribute(packages);
         }
 
         @Override
@@ -348,13 +435,13 @@
     }
 
     /**
-     * Version attribute.
+     * ModuleVersion attribute.
      *
      * <pre> {@code
      *
-     * Version_attribute {
+     * ModuleVersion_attribute {
      *   // index to CONSTANT_utf8_info structure in constant pool representing
-     *   // the string "Version"
+     *   // the string "ModuleVersion"
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
@@ -364,15 +451,15 @@
      *
      * } </pre>
      */
-    static class VersionAttribute extends Attribute {
+    public static class ModuleVersionAttribute extends Attribute {
         private final Version version;
 
-        VersionAttribute(Version version) {
-            super(VERSION);
+        public ModuleVersionAttribute(Version version) {
+            super(MODULE_VERSION);
             this.version = version;
         }
 
-        VersionAttribute() {
+        public ModuleVersionAttribute() {
             this(null);
         }
 
@@ -385,7 +472,7 @@
                                  Label[] labels)
         {
             String value = cr.readUTF8(off, buf);
-            return new VersionAttribute(Version.parse(value));
+            return new ModuleVersionAttribute(Version.parse(value));
         }
 
         @Override
@@ -403,13 +490,13 @@
     }
 
     /**
-     * MainClass attribute.
+     * ModuleMainClass attribute.
      *
      * <pre> {@code
      *
      * MainClass_attribute {
      *   // index to CONSTANT_utf8_info structure in constant pool representing
-     *   // the string "MainClass"
+     *   // the string "ModuleMainClass"
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
@@ -419,15 +506,15 @@
      *
      * } </pre>
      */
-    static class MainClassAttribute extends Attribute {
+    public static class ModuleMainClassAttribute extends Attribute {
         private final String mainClass;
 
-        MainClassAttribute(String mainClass) {
-            super(MAIN_CLASS);
+        public ModuleMainClassAttribute(String mainClass) {
+            super(MODULE_MAIN_CLASS);
             this.mainClass = mainClass;
         }
 
-        MainClassAttribute() {
+        public ModuleMainClassAttribute() {
             this(null);
         }
 
@@ -440,7 +527,7 @@
                                  Label[] labels)
         {
             String value = cr.readClass(off, buf);
-            return new MainClassAttribute(value);
+            return new ModuleMainClassAttribute(value);
         }
 
         @Override
@@ -458,13 +545,13 @@
     }
 
     /**
-     * TargetPlatform attribute.
+     * ModuleTarget attribute.
      *
      * <pre> {@code
      *
      * TargetPlatform_attribute {
      *   // index to CONSTANT_utf8_info structure in constant pool representing
-     *   // the string "TargetPlatform"
+     *   // the string "ModuleTarget"
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
@@ -478,19 +565,19 @@
      *
      * } </pre>
      */
-    static class TargetPlatformAttribute extends Attribute {
+    public static class ModuleTargetAttribute extends Attribute {
         private final String osName;
         private final String osArch;
         private final String osVersion;
 
-        TargetPlatformAttribute(String osName, String osArch, String osVersion) {
-            super(TARGET_PLATFORM);
+        public ModuleTargetAttribute(String osName, String osArch, String osVersion) {
+            super(MODULE_TARGET);
             this.osName = osName;
             this.osArch = osArch;
             this.osVersion = osVersion;
         }
 
-        TargetPlatformAttribute() {
+        public ModuleTargetAttribute() {
             this(null, null, null);
         }
 
@@ -522,7 +609,7 @@
                 osVersion = cr.readUTF8(off, buf);
             off += 2;
 
-            return new TargetPlatformAttribute(osName, osArch, osVersion);
+            return new ModuleTargetAttribute(osName, osArch, osVersion);
         }
 
         @Override
@@ -554,39 +641,37 @@
     }
 
     /**
-     * Hashes attribute.
+     * ModuleHashes attribute.
      *
      * <pre> {@code
      *
-     * Hashes_attribute {
+     * ModuleHashes_attribute {
      *   // index to CONSTANT_utf8_info structure in constant pool representing
-     *   // the string "Hashes"
+     *   // the string "ModuleHashes"
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
-     *   // index to CONSTANT_CONSTANT_utf8_info structure with algorithm name
+     *   // index to CONSTANT_utf8_info structure with algorithm name
      *   u2 algorithm_index;
      *
      *   // the number of entries in the hashes table
-     *   u2 hash_count;
-     *   {   u2 requires_index
-     *       u2 hash_index;
-     *   } hashes[hash_count];
+     *   u2 hashes_count;
+     *   {   u2 module_name_index
+     *       u2 hash_length;
+     *       u1 hash[hash_length];
+     *   } hashes[hashes_count];
      *
      * } </pre>
-     *
-     * @apiNote For now the hash is stored in base64 as a UTF-8 string, an
-     * alternative is to store it as an array of u1.
      */
-    static class HashesAttribute extends Attribute {
+    static class ModuleHashesAttribute extends Attribute {
         private final ModuleHashes hashes;
 
-        HashesAttribute(ModuleHashes hashes) {
-            super(HASHES);
+        ModuleHashesAttribute(ModuleHashes hashes) {
+            super(MODULE_HASHES);
             this.hashes = hashes;
         }
 
-        HashesAttribute() {
+        ModuleHashesAttribute() {
             this(null);
         }
 
@@ -601,21 +686,28 @@
             String algorithm = cr.readUTF8(off, buf);
             off += 2;
 
-            int hash_count = cr.readUnsignedShort(off);
+            int hashes_count = cr.readUnsignedShort(off);
             off += 2;
 
-            Map<String, String> map = new HashMap<>();
-            for (int i=0; i<hash_count; i++) {
-                String dn = cr.readUTF8(off, buf);
+            Map<String, byte[]> map = new HashMap<>();
+            for (int i=0; i<hashes_count; i++) {
+                String mn = cr.readUTF8(off, buf).replace('/', '.');
                 off += 2;
-                String hash = cr.readUTF8(off, buf);
+
+                int hash_length = cr.readUnsignedShort(off);
                 off += 2;
-                map.put(dn, hash);
+                byte[] hash = new byte[hash_length];
+                for (int j=0; j<hash_length; j++) {
+                    hash[j] = (byte) (0xff & cr.readByte(off+j));
+                }
+                off += hash_length;
+
+                map.put(mn, hash);
             }
 
             ModuleHashes hashes = new ModuleHashes(algorithm, map);
 
-            return new HashesAttribute(hashes);
+            return new ModuleHashesAttribute(hashes);
         }
 
         @Override
@@ -633,11 +725,15 @@
             Set<String> names = hashes.names();
             attr.putShort(names.size());
 
-            for (String dn : names) {
-                String hash = hashes.hashFor(dn);
+            for (String mn : names) {
+                byte[] hash = hashes.hashFor(mn);
                 assert hash != null;
-                attr.putShort(cw.newUTF8(dn));
-                attr.putShort(cw.newUTF8(hash));
+                attr.putShort(cw.newUTF8(mn.replace('.', '/')));
+
+                attr.putShort(hash.length);
+                for (byte b: hash) {
+                    attr.putByte(b);
+                }
             }
 
             return attr;
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileConstants.java b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileConstants.java
index 6a61f09..bf8955c 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileConstants.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileConstants.java
@@ -35,19 +35,20 @@
     // Attribute names
     public static final String MODULE             = "Module";
     public static final String SOURCE_FILE        = "SourceFile";
-    public static final String SYNTHETIC          = "Synthetic";
     public static final String SDE                = "SourceDebugExtension";
 
-    public static final String CONCEALED_PACKAGES = "ConcealedPackages";
-    public static final String VERSION            = "Version";
-    public static final String MAIN_CLASS         = "MainClass";
-    public static final String TARGET_PLATFORM    = "TargetPlatform";
-    public static final String HASHES             = "Hashes";
+    public static final String MODULE_PACKAGES    = "ModulePackages";
+    public static final String MODULE_VERSION     = "ModuleVersion";
+    public static final String MODULE_MAIN_CLASS  = "ModuleMainClass";
+    public static final String MODULE_TARGET      = "ModuleTarget";
+    public static final String MODULE_HASHES      = "ModuleHashes";
 
-    // access and requires flags
-    public static final int ACC_MODULE       = 0x8000;
-    public static final int ACC_PUBLIC       = 0x0020;
-    public static final int ACC_SYNTHETIC    = 0x1000;
-    public static final int ACC_MANDATED     = 0x8000;
+    // access, requires, exports, and opens flags
+    public static final int ACC_MODULE        = 0x8000;
+    public static final int ACC_OPEN          = 0x0020;
+    public static final int ACC_TRANSITIVE    = 0x0010;
+    public static final int ACC_STATIC_PHASE  = 0x0020;
+    public static final int ACC_SYNTHETIC     = 0x1000;
+    public static final int ACC_MANDATED      = 0x8000;
 
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
index cacb979..1a00ede 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
@@ -37,9 +37,11 @@
 import java.net.URI;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -81,10 +83,20 @@
     // the token for "all modules on the module path"
     private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
 
+    // The ModulePatcher for the initial configuration
+    private static final ModulePatcher patcher = initModulePatcher();
+
     // ModuleFinder for the initial configuration
     private static ModuleFinder initialFinder;
 
     /**
+     * Returns the ModulePatcher for the initial configuration.
+     */
+    public static ModulePatcher patcher() {
+        return patcher;
+    }
+
+    /**
      * Returns the ModuleFinder for the initial configuration
      */
     public static ModuleFinder finder() {
@@ -101,7 +113,7 @@
 
         long t0 = System.nanoTime();
 
-        // system modules
+        // system modules (may be patched)
         ModuleFinder systemModules = ModuleFinder.ofSystem();
 
         PerfCounters.systemModulesTime.addElapsedTimeFrom(t0);
@@ -247,7 +259,7 @@
         if (baseUri.getScheme().equals("jrt")   // toLowerCase not needed here
                 && (upgradeModulePath == null)
                 && (appModulePath == null)
-                && (!ModulePatcher.isBootLayerPatched())) {
+                && (patcher.isEmpty())) {
             needPostResolutionChecks = false;
         }
 
@@ -314,9 +326,9 @@
         PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
 
 
-        // --add-reads and --add-exports
+        // --add-reads, -add-exports/-add-opens
         addExtraReads(bootLayer);
-        addExtraExports(bootLayer);
+        addExtraExportsAndOpens(bootLayer);
 
         // total time to initialize
         PerfCounters.bootstrapTime.addElapsedTimeFrom(t0);
@@ -389,6 +401,18 @@
         }
     }
 
+
+    /**
+     * Initialize the module patcher for the initial configuration passed on the
+     * value of the --patch-module options.
+     */
+    private static ModulePatcher initModulePatcher() {
+        Map<String, List<String>> map = decode("jdk.module.patch.",
+                                               File.pathSeparator,
+                                               false);
+        return new ModulePatcher(map);
+    }
+
     /**
      * Returns the set of module names specified via --add-modules options
      * on the command line
@@ -408,7 +432,6 @@
             for (String s : value.split(",")) {
                 if (s.length() > 0) modules.add(s);
             }
-
             index++;
             value = getAndRemoveProperty(prefix + index);
         }
@@ -423,9 +446,11 @@
     private static void addExtraReads(Layer bootLayer) {
 
         // decode the command line options
-        Map<String, Set<String>> map = decode("jdk.module.addreads.");
+        Map<String, List<String>> map = decode("jdk.module.addreads.");
+        if (map.isEmpty())
+            return;
 
-        for (Map.Entry<String, Set<String>> e : map.entrySet()) {
+        for (Map.Entry<String, List<String>> e : map.entrySet()) {
 
             // the key is $MODULE
             String mn = e.getKey();
@@ -448,22 +473,36 @@
                         warn("Unknown module: " + name);
                     }
                 }
-
             }
         }
     }
 
-
     /**
-     * Process the --add-exports options to add any additional read edges that
-     * are specified on the command-line.
+     * Process the --add-exports and --add-opens options to export/open
+     * additional packages specified on the command-line.
      */
-    private static void addExtraExports(Layer bootLayer) {
+    private static void addExtraExportsAndOpens(Layer bootLayer) {
 
-        // decode the command line options
-        Map<String, Set<String>> map = decode("jdk.module.addexports.");
+        // --add-exports
+        String prefix = "jdk.module.addexports.";
+        Map<String, List<String>> extraExports = decode(prefix);
+        if (!extraExports.isEmpty()) {
+            addExtraExportsOrOpens(bootLayer, extraExports, false);
+        }
 
-        for (Map.Entry<String, Set<String>> e : map.entrySet()) {
+        // --add-opens
+        prefix = "jdk.module.addopens.";
+        Map<String, List<String>> extraOpens = decode(prefix);
+        if (!extraOpens.isEmpty()) {
+            addExtraExportsOrOpens(bootLayer, extraOpens, true);
+        }
+    }
+
+    private static void addExtraExportsOrOpens(Layer bootLayer,
+                                               Map<String, List<String>> map,
+                                               boolean opens)
+    {
+        for (Map.Entry<String, List<String>> e : map.entrySet()) {
 
             // the key is $MODULE/$PACKAGE
             String key = e.getKey();
@@ -507,28 +546,40 @@
                     }
                 }
                 if (allUnnamed) {
-                    Modules.addExportsToAllUnnamed(m, pn);
+                    if (opens) {
+                        Modules.addOpensToAllUnnamed(m, pn);
+                    } else {
+                        Modules.addExportsToAllUnnamed(m, pn);
+                    }
                 } else {
-                    Modules.addExports(m, pn, other);
+                    if (opens) {
+                        Modules.addOpens(m, pn, other);
+                    } else {
+                        Modules.addExports(m, pn, other);
+                    }
                 }
+
             }
         }
     }
 
-
     /**
-     * Decodes the values of --add-reads or --add-exports options
+     * Decodes the values of --add-reads, -add-exports, --add-opens or
+     * --patch-modules options that are encoded in system properties.
      *
-     * The format of the options is: $KEY=$MODULE(,$MODULE)*
+     * @param prefix the system property prefix
+     * @praam regex the regex for splitting the RHS of the option value
      */
-    private static Map<String, Set<String>> decode(String prefix) {
+    private static Map<String, List<String>> decode(String prefix,
+                                                    String regex,
+                                                    boolean allowDuplicates) {
         int index = 0;
         // the system property is removed after decoding
         String value = getAndRemoveProperty(prefix + index);
         if (value == null)
             return Collections.emptyMap();
 
-        Map<String, Set<String>> map = new HashMap<>();
+        Map<String, List<String>> map = new HashMap<>();
 
         while (value != null) {
 
@@ -545,8 +596,11 @@
             if (rhs.isEmpty())
                 fail("Unable to parse: " + value);
 
-            Set<String> values = map.computeIfAbsent(key, k -> new HashSet<>());
-            for (String s : rhs.split(",")) {
+            // value is <module>(,<module>)* or <file>(<pathsep><file>)*
+            if (!allowDuplicates && map.containsKey(key))
+                fail(key + " specified more than once");
+            List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>());
+            for (String s : rhs.split(regex)) {
                 if (s.length() > 0) values.add(s);
             }
 
@@ -558,6 +612,14 @@
     }
 
     /**
+     * Decodes the values of --add-reads, -add-exports or --add-opens
+     * which use the "," to separate the RHS of the option value.
+     */
+    private static Map<String, List<String>> decode(String prefix) {
+        return decode(prefix, ",", true);
+    }
+
+    /**
      * Gets and remove the named system property
      */
     private static String getAndRemoveProperty(String key) {
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
index 2012c78..107305e 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
@@ -32,7 +32,6 @@
 import java.nio.file.Path;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.util.Base64;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -45,23 +44,23 @@
 public final class ModuleHashes {
 
     /**
-     * A supplier of an encoded message digest.
+     * A supplier of a message digest.
      */
     public static interface HashSupplier {
-        String generate(String algorithm);
+        byte[] generate(String algorithm);
     }
 
 
     private final String algorithm;
-    private final Map<String, String> nameToHash;
+    private final Map<String, byte[]> nameToHash;
 
     /**
      * Creates a {@code ModuleHashes}.
      *
      * @param algorithm   the algorithm used to create the hashes
-     * @param nameToHash  the map of module name to hash value (in string form)
+     * @param nameToHash  the map of module name to hash value
      */
-    public ModuleHashes(String algorithm, Map<String, String> nameToHash) {
+    public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
         this.algorithm = algorithm;
         this.nameToHash = Collections.unmodifiableMap(nameToHash);
     }
@@ -81,28 +80,28 @@
     }
 
     /**
-     * Returns the hash string for the given module name, {@code null}
+     * Returns the hash for the given module name, {@code null}
      * if there is no hash recorded for the module.
      */
-    public String hashFor(String mn) {
+    public byte[] hashFor(String mn) {
         return nameToHash.get(mn);
     }
 
     /**
-     * Returns unmodifiable map of module name to hash string.
+     * Returns unmodifiable map of module name to hash
      */
-    public Map<String, String> hashes() {
+    public Map<String, byte[]> hashes() {
         return nameToHash;
     }
 
     /**
      * Computes the hash for the given file with the given message digest
-     * algorithm. Returns the results a base64-encoded String.
+     * algorithm.
      *
      * @throws UncheckedIOException if an I/O error occurs
      * @throws RuntimeException if the algorithm is not available
      */
-    public static String computeHashAsString(Path file, String algorithm) {
+    public static byte[] computeHash(Path file, String algorithm) {
         try {
             MessageDigest md = MessageDigest.getInstance(algorithm);
 
@@ -118,8 +117,7 @@
                 }
             }
 
-            byte[] bytes = md.digest();
-            return Base64.getEncoder().encodeToString(bytes);
+            return md.digest();
         } catch (NoSuchAlgorithmException e) {
             throw new RuntimeException(e);
         } catch (IOException ioe) {
@@ -133,14 +131,14 @@
      * the entry name, typically the module name. The map value is the file
      * path to the entry (module artifact).
      *
-     * @return ModuleHashes encapsulate the hashes
+     * @return ModuleHashes that encapsulates the hashes
      */
     public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
-        Map<String, String> nameToHash = new HashMap<>();
+        Map<String, byte[]> nameToHash = new HashMap<>();
         for (Map.Entry<String, Path> entry: map.entrySet()) {
             String name = entry.getKey();
             Path path = entry.getValue();
-            nameToHash.put(name, computeHashAsString(path, algorithm));
+            nameToHash.put(name, computeHash(path, algorithm));
         }
         return new ModuleHashes(algorithm, nameToHash);
     }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
index 3c44964..07bb402 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
@@ -53,8 +53,8 @@
     // the input stream to read the original module-info.class
     private final InputStream in;
 
-    // the packages in the ConcealedPackages attribute
-    private Set<String> conceals;
+    // the packages in the Packages attribute
+    private Set<String> packages;
 
     // the value of the Version attribute
     private Version version;
@@ -75,10 +75,10 @@
     }
 
     /**
-     * Sets the set of packages for the ConcealedPackages attribute
+     * Sets the set of packages for the Packages attribute
      */
-    public ModuleInfoExtender conceals(Set<String> packages) {
-        this.conceals = Collections.unmodifiableSet(packages);
+    public ModuleInfoExtender packages(Set<String> packages) {
+        this.packages = Collections.unmodifiableSet(packages);
         return this;
     }
 
@@ -181,26 +181,26 @@
 
         ClassReader cr = new ClassReader(in);
 
-        if (conceals != null)
-            cv.addAttribute(new ConcealedPackagesAttribute(conceals));
+        if (packages != null)
+            cv.addAttribute(new ModulePackagesAttribute(packages));
         if (version != null)
-            cv.addAttribute(new VersionAttribute(version));
+            cv.addAttribute(new ModuleVersionAttribute(version));
         if (mainClass != null)
-            cv.addAttribute(new MainClassAttribute(mainClass));
+            cv.addAttribute(new ModuleMainClassAttribute(mainClass));
         if (osName != null || osArch != null || osVersion != null)
-            cv.addAttribute(new TargetPlatformAttribute(osName, osArch, osVersion));
+            cv.addAttribute(new ModuleTargetAttribute(osName, osArch, osVersion));
         if (hashes != null)
-            cv.addAttribute(new HashesAttribute(hashes));
+            cv.addAttribute(new ModuleHashesAttribute(hashes));
 
         List<Attribute> attrs = new ArrayList<>();
 
         // prototypes of attributes that should be parsed
         attrs.add(new ModuleAttribute());
-        attrs.add(new ConcealedPackagesAttribute());
-        attrs.add(new VersionAttribute());
-        attrs.add(new MainClassAttribute());
-        attrs.add(new TargetPlatformAttribute());
-        attrs.add(new HashesAttribute());
+        attrs.add(new ModulePackagesAttribute());
+        attrs.add(new ModuleVersionAttribute());
+        attrs.add(new ModuleMainClassAttribute());
+        attrs.add(new ModuleTargetAttribute());
+        attrs.add(new ModuleHashesAttribute());
 
         cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
 
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
index a8dda9b..5e4efff 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
@@ -27,9 +27,8 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Version;
 import java.nio.ByteBuffer;
-import java.util.Optional;
+import java.util.stream.Stream;
 
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
@@ -52,31 +51,28 @@
     private static byte[] toModuleInfo(ModuleDescriptor md) {
 
         ClassWriter cw = new ClassWriter(0);
-
-        String name = md.name().replace('.', '/') + "/module-info";
-        cw.visit(Opcodes.V1_9, ACC_MODULE, name, null, null, null);
-
+        cw.visit(Opcodes.V1_9, ACC_MODULE, null, null, null, null);
         cw.visitAttribute(new ModuleAttribute(md));
 
-        // for tests: write the ConcealedPackages attribute when there are non-exported packages
-        long nExportedPackages = md.exports().stream()
-                .map(ModuleDescriptor.Exports::source)
-                .distinct()
-                .count();
-        if (md.packages().size() > nExportedPackages)
-            cw.visitAttribute(new ConcealedPackagesAttribute(md.packages()));
+        // for tests: write the Packages attribute when there are packages that
+        // aren't exported or open
+        Stream<String> exported = md.exports().stream()
+                .map(ModuleDescriptor.Exports::source);
+        Stream<String> open = md.opens().stream()
+                .map(ModuleDescriptor.Opens::source);
+        long exportedOrOpen = Stream.concat(exported, open).distinct().count();
+        if (md.packages().size() > exportedOrOpen)
+            cw.visitAttribute(new ModulePackagesAttribute(md.packages()));
 
-        md.version().ifPresent(v -> cw.visitAttribute(new VersionAttribute(v)));
-        md.mainClass().ifPresent(mc -> cw.visitAttribute(new MainClassAttribute(mc)));
+        md.version().ifPresent(v -> cw.visitAttribute(new ModuleVersionAttribute(v)));
+        md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
 
         // write the TargetPlatform attribute if have any of OS name/arch/version
         String osName = md.osName().orElse(null);
         String osArch = md.osArch().orElse(null);
         String osVersion = md.osVersion().orElse(null);
         if (osName != null || osArch != null || osVersion != null) {
-            cw.visitAttribute(new TargetPlatformAttribute(osName,
-                                                          osArch,
-                                                          osVersion));
+            cw.visitAttribute(new ModuleTargetAttribute(osName, osArch, osVersion));
         }
 
         cw.visitEnd();
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
index afee8bf..97966bd 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java
@@ -50,6 +50,7 @@
 import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import jdk.internal.loader.Resource;
@@ -59,7 +60,7 @@
 
 
 /**
- * Provides support for patching modules in the boot layer with --patch-module.
+ * Provides support for patching modules, mostly the boot layer.
  */
 
 public final class ModulePatcher {
@@ -67,89 +68,46 @@
     private static final JavaLangModuleAccess JLMA
         = SharedSecrets.getJavaLangModuleAccess();
 
-    // the prefix of the system properties that encode the value of --patch-module
-    private static final String PATCH_PROPERTY_PREFIX = "jdk.module.patch.";
-
     // module name -> sequence of patches (directories or JAR files)
-    private static final Map<String, List<Path>> PATCH_MAP = decodeProperties();
-
-    private ModulePatcher() { }
+    private final Map<String, List<Path>> map;
 
     /**
-     * Decodes the values of --patch-module options, returning a Map of module
-     * name to list of file paths.
-     *
-     * @throws IllegalArgumentException if the the module name is missing or
-     *         --patch-module is used more than once to patch the same module
+     * Initialize the module patcher with the given map. The map key is
+     * the module name, the value is a list of path strings.
      */
-    private static Map<String, List<Path>> decodeProperties() {
-
-        int index = 0;
-        String value = getAndRemoveProperty(PATCH_PROPERTY_PREFIX + index);
-        if (value == null)
-            return Collections.emptyMap();  // --patch-module not specified
-
-        Map<String, List<Path>> map = new HashMap<>();
-        while (value != null) {
-
-            // <module>=<file>(:<file>)*
-
-            int pos = value.indexOf('=');
-            if (pos == -1)
-                throwIAE("Unable to parse: " + value);
-            if (pos == 0)
-                throwIAE("Missing module name: " + value);
-
-            String mn = value.substring(0, pos);
-            List<Path> list = map.get(mn);
-            if (list != null)
-                throwIAE("Module " + mn + " specified more than once");
-            list = new ArrayList<>();
-            map.put(mn, list);
-
-            String paths = value.substring(pos+1);
-            for (String path : paths.split(File.pathSeparator)) {
-                if (!path.isEmpty()) {
-                    list.add(Paths.get(path));
-                }
+    public ModulePatcher(Map<String, List<String>> input) {
+        if (input.isEmpty()) {
+            this.map = Collections.emptyMap();
+        } else {
+            Map<String, List<Path>> map = new HashMap<>();
+            for (Map.Entry<String, List<String>> e : input.entrySet()) {
+                String mn = e.getKey();
+                List<Path> paths = e.getValue().stream()
+                        .map(Paths::get)
+                        .collect(Collectors.toList());
+                map.put(mn, paths);
             }
-
-            index++;
-            value = getAndRemoveProperty(PATCH_PROPERTY_PREFIX + index);
+            this.map = map;
         }
-
-        return map;
-    }
-
-
-    /**
-     * Returns {@code true} is --patch-module is specified to patch modules
-     * in the boot layer.
-     */
-    static boolean isBootLayerPatched() {
-        return !PATCH_MAP.isEmpty();
     }
 
     /**
      * Returns a module reference that interposes on the given module if
      * needed. If there are no patches for the given module then the module
      * reference is simply returned. Otherwise the patches for the module
-     * are scanned (to find any new concealed packages) and a new module
-     * reference is returned.
+     * are scanned (to find any new packages) and a new module reference is
+     * returned.
      *
      * @throws UncheckedIOException if an I/O error is detected
      */
-    public static ModuleReference interposeIfNeeded(ModuleReference mref) {
-
+    public ModuleReference patchIfNeeded(ModuleReference mref) {
+        // if there are no patches for the module then nothing to do
         ModuleDescriptor descriptor = mref.descriptor();
         String mn = descriptor.name();
-
-        // if there are no patches for the module then nothing to do
-        List<Path> paths = PATCH_MAP.get(mn);
+        List<Path> paths = map.get(mn);
         if (paths == null)
             return mref;
 
-
         // scan the JAR file or directory tree to get the set of packages
         Set<String> packages = new HashSet<>();
         try {
@@ -197,6 +155,13 @@
 
     }
 
+    /**
+     * Returns true is this module patcher has no patches.
+     */
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
 
     /**
      * A ModuleReader that reads resources from a patched module.
@@ -569,13 +534,6 @@
     }
 
     /**
-     * Gets and remove the named system property
-     */
-    private static String getAndRemoveProperty(String key) {
-        return (String)System.getProperties().remove(key);
-    }
-
-    /**
      * Derives a package name from the name of an entry in a JAR file.
      */
     private static String toPackageName(Path file, JarEntry entry) {
@@ -593,9 +551,4 @@
             System.err.println("WARNING: " + e + " ignored in patch: " + file);
         return "";
     }
-
-    private static void throwIAE(String msg) {
-        throw new IllegalArgumentException(msg);
-    }
-
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
index 9a0248a..9f68cfb 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java
@@ -26,8 +26,11 @@
 package jdk.internal.module;
 
 import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Layer;
 import java.lang.reflect.Module;
 import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Set;
 
 import jdk.internal.loader.BootLoader;
@@ -35,7 +38,6 @@
 import jdk.internal.misc.JavaLangReflectModuleAccess;
 import jdk.internal.misc.SharedSecrets;
 
-
 /**
  * A helper class to allow JDK classes create dynamic modules and to update
  * modules, exports and the readability graph. It is also invoked by the VM
@@ -53,7 +55,6 @@
     private static final JavaLangReflectModuleAccess JLRMA
         = SharedSecrets.getJavaLangReflectModuleAccess();
 
-
     /**
      * Creates a new Module. The module has the given ModuleDescriptor and
      * is defined to the given class loader.
@@ -72,7 +73,7 @@
 
     /**
      * Define a new module to the VM. The module has the given set of
-     * concealed packages and is defined to the given class loader.
+     * packages and is defined to the given class loader.
      *
      * The resulting Module is in a larval state in that it does not not read
      * any other module and does not have any exports.
@@ -81,8 +82,9 @@
                                       String name,
                                       Set<String> packages)
     {
-        ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder(name).conceals(packages).build();
+        ModuleDescriptor descriptor = ModuleDescriptor.module(name)
+                .contains(packages)
+                .build();
 
         return JLRMA.defineModule(loader, descriptor, null);
     }
@@ -104,13 +106,21 @@
 
     /**
      * Updates module m1 to export a package to module m2.
-     * Same as m1.addExports(pkg, m2) but without a caller check.
+     * Same as m1.addExports(pn, m2) but without a caller check.
      */
     public static void addExports(Module m1, String pn, Module m2) {
         JLRMA.addExports(m1, pn, m2);
     }
 
     /**
+     * Updates module m1 to open a package to module m2.
+     * Same as m1.addOpens(pn, m2) but without a caller check.
+     */
+    public static void addOpens(Module m1, String pn, Module m2) {
+        JLRMA.addOpens(m1, pn, m2);
+    }
+
+    /**
      * Updates a module m to export a package to all modules.
      */
     public static void addExportsToAll(Module m, String pn) {
@@ -118,6 +128,13 @@
     }
 
     /**
+     * Updates a module m to open a package to all modules.
+     */
+    public static void addOpensToAll(Module m, String pn) {
+        JLRMA.addOpensToAll(m, pn);
+    }
+
+    /**
      * Updates module m to export a package to all unnamed modules.
      */
     public static void addExportsToAllUnnamed(Module m, String pn) {
@@ -125,6 +142,47 @@
     }
 
     /**
+     * Updates module m to open a package to all unnamed modules.
+     */
+    public static void addOpensToAllUnnamed(Module m, String pn) {
+        JLRMA.addOpensToAllUnnamed(m, pn);
+    }
+
+    /**
+     * Updates module m to use a service
+     */
+    public static void addUses(Module m, Class<?> service) {
+        JLRMA.addUses(m, service);
+    }
+
+    /**
+     * Updates module m to provide a service
+     */
+    public static void addProvides(Module m, Class<?> service, Class<?> impl) {
+        Layer layer = m.getLayer();
+
+        if (layer == null || layer == Layer.boot()) {
+            // update ClassLoader catalog
+            PrivilegedAction<ClassLoader> pa = m::getClassLoader;
+            ClassLoader loader = AccessController.doPrivileged(pa);
+            ServicesCatalog catalog;
+            if (loader == null) {
+                catalog = BootLoader.getServicesCatalog();
+            } else {
+                catalog = ServicesCatalog.getServicesCatalog(loader);
+            }
+            catalog.addProvider(m, service, impl);
+        }
+
+        if (layer != null) {
+            // update Layer catalog
+            SharedSecrets.getJavaLangReflectModuleAccess()
+                    .getServicesCatalog(layer)
+                    .addProvider(m, service, impl);
+        }
+    }
+
+    /**
      * Adds a package to a module's content.
      *
      * This method is a no-op if the module already contains the package.
@@ -142,5 +200,4 @@
         addReads(m, BootLoader.getUnnamedModule());
         addReads(m, ClassLoaders.appClassLoader().getUnnamedModule());
     }
-
 }
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java
index 92b8058..d4425aa 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java
@@ -28,20 +28,24 @@
 import java.lang.reflect.Module;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Provides;
+import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import jdk.internal.loader.ClassLoaderValue;
 
 /**
  * A <em>services catalog</em>. Each {@code ClassLoader} and {@code Layer} has
  * an optional {@code ServicesCatalog} for modules that provide services.
  *
- * @see java.util.ServiceLoader
+ * @apiNote This class will be replaced once the ServiceLoader is further
+ *          specified
  */
-public interface ServicesCatalog {
+public final class ServicesCatalog {
 
     /**
      * Represents a service provider in the services catalog.
@@ -78,56 +82,98 @@
         }
     }
 
-    /**
-     * Registers the providers in the given module in this services catalog.
-     *
-     * @throws UnsupportedOperationException
-     *         If this services catalog is immutable
-     */
-    void register(Module module);
+    // service name -> list of providers
+    private final Map<String, List<ServiceProvider>> map = new ConcurrentHashMap<>();
 
-    /**
-     * Returns the (possibly empty) set of service providers that implement the
-     * given service type.
-     */
-    Set<ServiceProvider> findServices(String service);
+    private ServicesCatalog() { }
 
     /**
      * Creates a ServicesCatalog that supports concurrent registration and
-     * and lookup.
+     * and lookup
      */
-    static ServicesCatalog create() {
-        return new ServicesCatalog() {
-
-            private Map<String, Set<ServiceProvider>> map = new ConcurrentHashMap<>();
-
-            @Override
-            public void register(Module m) {
-                ModuleDescriptor descriptor = m.getDescriptor();
-
-                for (Provides provides : descriptor.provides().values()) {
-                    String service = provides.service();
-                    Set<String> providerNames = provides.providers();
-
-                    // create a new set to replace the existing
-                    Set<ServiceProvider> result = new HashSet<>();
-                    Set<ServiceProvider> providers = map.get(service);
-                    if (providers != null) {
-                        result.addAll(providers);
-                    }
-                    for (String pn : providerNames) {
-                        result.add(new ServiceProvider(m, pn));
-                    }
-                    map.put(service, Collections.unmodifiableSet(result));
-                }
-
-            }
-
-            @Override
-            public Set<ServiceProvider> findServices(String service) {
-                return map.getOrDefault(service, Collections.emptySet());
-            }
-
-        };
+    public static ServicesCatalog create() {
+        return new ServicesCatalog();
     }
+
+    /**
+     * Returns the list of service provides for the given service type
+     * name, creating it if needed.
+     */
+    private List<ServiceProvider> providers(String service) {
+        // avoid computeIfAbsent here
+        List<ServiceProvider> list = map.get(service);
+        if (list == null) {
+            list = new CopyOnWriteArrayList<>();
+            List<ServiceProvider> prev = map.putIfAbsent(service, list);
+            if (prev != null)
+                list = prev;  // someone else got there
+        }
+        return list;
+    }
+
+    /**
+     * Registers the providers in the given module in this services catalog.
+     */
+    public void register(Module module) {
+        ModuleDescriptor descriptor = module.getDescriptor();
+        for (Provides provides : descriptor.provides()) {
+            String service = provides.service();
+            List<String> providerNames = provides.providers();
+            int count = providerNames.size();
+            if (count == 1) {
+                String pn = providerNames.get(0);
+                providers(service).add(new ServiceProvider(module, pn));
+            } else {
+                List<ServiceProvider> list = new ArrayList<>(count);
+                for (String pn : providerNames) {
+                    list.add(new ServiceProvider(module, pn));
+                }
+                providers(service).addAll(list);
+            }
+        }
+    }
+
+    /**
+     * Add a provider in the given module to this services catalog
+     *
+     * @apiNote This method is for use by java.lang.instrument
+     */
+    public void addProvider(Module module, Class<?> service, Class<?> impl) {
+        List<ServiceProvider> list = providers(service.getName());
+        list.add(new ServiceProvider(module, impl.getName()));
+    }
+
+    /**
+     * Returns the (possibly empty) list of service providers that implement
+     * the given service type.
+     */
+    public List<ServiceProvider> findServices(String service) {
+        return map.getOrDefault(service, Collections.emptyList());
+    }
+
+    /**
+     * Returns the ServicesCatalog for the given class loader or {@code null}
+     * if there is none.
+     */
+    public static ServicesCatalog getServicesCatalogOrNull(ClassLoader loader) {
+        return CLV.get(loader);
+    }
+
+    /**
+     * Returns the ServicesCatalog for the given class loader, creating it if
+     * needed.
+     */
+    public static ServicesCatalog getServicesCatalog(ClassLoader loader) {
+        // CLV.computeIfAbsent(loader, (cl, clv) -> create());
+        ServicesCatalog catalog = CLV.get(loader);
+        if (catalog == null) {
+            catalog = create();
+            ServicesCatalog previous = CLV.putIfAbsent(loader, catalog);
+            if (previous != null) catalog = previous;
+        }
+        return catalog;
+    }
+
+    // the ServicesCatalog registered to a class loader
+    private static final ClassLoaderValue<ServicesCatalog> CLV = new ClassLoaderValue<>();
 }
\ No newline at end of file
diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
index 78619f0..299c622 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java
@@ -51,7 +51,7 @@
     /**
      * Hash of system modules.
      */
-    public static String[] MODULES_TO_HASH = new String[0];
+    public static byte[][] MODULES_TO_HASH = new byte[0][];
 
     /**
      * Number of packages in the boot layer from the installed modules.
diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
index 2e3d62b..a577f93 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java
@@ -695,7 +695,7 @@
             final String[] interfaces) {
         this.version = version;
         this.access = access;
-        this.name = newClass(name);
+        this.name = (name == null) ? 0 : newClass(name);
         thisName = name;
         if (ClassReader.SIGNATURES && signature != null) {
             this.signature = newUTF8(signature);
diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java
index b97c5f6..0c4cb74 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java
@@ -112,10 +112,13 @@
         }
     }
 
-    private static boolean verifyMemberAccess(Class<?> currentClass,
-                                              Class<?> memberClass,
-                                              Class<?> targetClass,
-                                              int modifiers)
+    /**
+     * Verify access to a member, returning {@code false} if no access
+     */
+    public static boolean verifyMemberAccess(Class<?> currentClass,
+                                             Class<?> memberClass,
+                                             Class<?> targetClass,
+                                             int modifiers)
     {
         // Verify that currentClass can access a field, method, or
         // constructor of memberClass, where that member's access bits are
diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java
index 0e4c035..ab4e031 100644
--- a/jdk/src/java.base/share/classes/module-info.java
+++ b/jdk/src/java.base/share/classes/module-info.java
@@ -115,16 +115,16 @@
     // additional qualified exports may be inserted at build time
     // see make/gensrc/GenModuleInfo.gmk
 
-    // CORBA serialization needs reflective access
-    exports sun.util.calendar to
-        java.corba;
-
     exports com.sun.security.ntlm to
         java.security.sasl;
     exports jdk.internal.jimage to
         jdk.jlink;
     exports jdk.internal.jimage.decompressor to
         jdk.jlink;
+    exports jdk.internal.loader to
+        java.instrument,
+        java.logging,
+        jdk.jlink;
     exports jdk.internal.jmod to
         jdk.compiler,
         jdk.jlink;
@@ -146,9 +146,6 @@
         jdk.scripting.nashorn;
     exports jdk.internal.org.objectweb.asm.signature to
         jdk.scripting.nashorn;
-    exports jdk.internal.loader to
-        java.instrument,
-        java.logging;
     exports jdk.internal.math to
         java.desktop;
     exports jdk.internal.module to
@@ -307,6 +304,8 @@
     // JDK-internal service types
     uses jdk.internal.logger.DefaultLoggerFinder;
     uses sun.security.ssl.ClientKeyExchangeService;
+    uses sun.security.util.AuthResourcesProvider;
+    uses sun.text.spi.JavaTimeDateTimePatternProvider;
     uses sun.util.spi.CalendarProvider;
     uses sun.util.locale.provider.LocaleDataMetaInfo;
     uses sun.util.resources.LocaleData.CommonResourceBundleProvider;
@@ -317,4 +316,6 @@
 
     provides java.nio.file.spi.FileSystemProvider with
         jdk.internal.jrtfs.JrtFileSystemProvider;
+    provides sun.security.util.AuthResourcesProvider with
+        sun.security.util.AuthResourcesProviderImpl;
 }
diff --git a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
index c5d8728..64e4be7 100644
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java
@@ -48,6 +48,7 @@
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.reflect.Layer;
 import java.lang.reflect.Method;
@@ -62,24 +63,29 @@
 import java.nio.file.Path;
 import java.text.Normalizer;
 import java.text.MessageFormat;
-import java.util.ResourceBundle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale.Category;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
-import java.util.Map;
+import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 import jdk.internal.misc.VM;
+import jdk.internal.module.Modules;
 
 
 public final class LauncherHelper {
@@ -95,6 +101,8 @@
     private static final String JAVAFX_FXHELPER_CLASS_NAME_SUFFIX =
             "sun.launcher.LauncherHelper$FXHelper";
     private static final String MAIN_CLASS = "Main-Class";
+    private static final String ADD_EXPORTS = "Add-Exports";
+    private static final String ADD_OPENS = "Add-Opens";
 
     private static StringBuilder outBuf = new StringBuilder();
 
@@ -413,11 +421,23 @@
             if (mainAttrs == null) {
                 abort(null, "java.launcher.jar.error3", jarname);
             }
+
+            // Main-Class
             mainValue = mainAttrs.getValue(MAIN_CLASS);
             if (mainValue == null) {
                 abort(null, "java.launcher.jar.error3", jarname);
             }
 
+            // Add-Exports and Add-Opens to break encapsulation
+            String exports = mainAttrs.getValue(ADD_EXPORTS);
+            if (exports != null) {
+                addExportsOrOpens(exports, false);
+            }
+            String opens = mainAttrs.getValue(ADD_OPENS);
+            if (opens != null) {
+                addExportsOrOpens(opens, true);
+            }
+
             /*
              * Hand off to FXHelper if it detects a JavaFX application
              * This must be done after ensuring a Main-Class entry
@@ -436,6 +456,29 @@
         return null;
     }
 
+    /**
+     * Process the Add-Exports or Add-Opens value. The value is
+     * {@code <module>/<package> ( <module>/<package>)*}.
+     */
+    static void addExportsOrOpens(String value, boolean open) {
+        for (String moduleAndPackage : value.split(" ")) {
+            String[] s = moduleAndPackage.trim().split("/");
+            if (s.length == 2) {
+                String mn = s[0];
+                String pn = s[1];
+                Layer.boot().findModule(mn).ifPresent(m -> {
+                    if (m.getDescriptor().packages().contains(pn)) {
+                        if (open) {
+                            Modules.addOpensToAllUnnamed(m, pn);
+                        } else {
+                            Modules.addExportsToAllUnnamed(m, pn);
+                        }
+                    }
+                });
+            }
+        }
+    }
+
     // From src/share/bin/java.c:
     //   enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE }
 
@@ -904,12 +947,26 @@
             for (String name: names) {
                 ModuleReference mref = finder.find(name).orElse(null);
                 if (mref == null) {
-                    // not found
+                    System.err.format("%s not observable!%n", name);
                     continue;
                 }
 
                 ModuleDescriptor md = mref.descriptor();
-                ostream.println(midAndLocation(md, mref.location()));
+                if (md.isOpen())
+                    ostream.print("open ");
+                if (md.isAutomatic())
+                    ostream.print("automatic ");
+                ostream.println("module " + midAndLocation(md, mref.location()));
+
+                // unqualified exports (sorted by package)
+                Set<Exports> exports = new TreeSet<>(Comparator.comparing(Exports::source));
+                md.exports().stream().filter(e -> !e.isQualified()).forEach(exports::add);
+                for (Exports e : exports) {
+                    String modsAndSource = Stream.concat(toStringStream(e.modifiers()),
+                            Stream.of(e.source()))
+                            .collect(Collectors.joining(" "));
+                    ostream.format("  exports %s%n", modsAndSource);
+                }
 
                 for (Requires d : md.requires()) {
                     ostream.format("  requires %s%n", d);
@@ -918,31 +975,51 @@
                     ostream.format("  uses %s%n", s);
                 }
 
-                // sorted exports
-                Set<Exports> exports = new TreeSet<>(Comparator.comparing(Exports::source));
-                exports.addAll(md.exports());
-                for (Exports e : exports) {
-                    ostream.format("  exports %s", e.source());
+                for (Provides ps : md.provides()) {
+                    ostream.format("  provides %s with %s%n", ps.service(),
+                            ps.providers().stream().collect(Collectors.joining(", ")));
+                }
+
+                // qualified exports
+                for (Exports e : md.exports()) {
                     if (e.isQualified()) {
+                        String modsAndSource = Stream.concat(toStringStream(e.modifiers()),
+                                Stream.of(e.source()))
+                                .collect(Collectors.joining(" "));
+                        ostream.format("  exports %s", modsAndSource);
                         formatCommaList(ostream, " to", e.targets());
-                    } else {
-                        ostream.println();
                     }
                 }
 
-                // concealed packages
-                new TreeSet<>(md.conceals())
-                    .forEach(p -> ostream.format("  conceals %s%n", p));
-
-                Map<String, Provides> provides = md.provides();
-                for (Provides ps : provides.values()) {
-                    for (String impl : ps.providers())
-                        ostream.format("  provides %s with %s%n", ps.service(), impl);
+                // open packages
+                for (Opens obj: md.opens()) {
+                    String modsAndSource = Stream.concat(toStringStream(obj.modifiers()),
+                            Stream.of(obj.source()))
+                            .collect(Collectors.joining(" "));
+                    ostream.format("  opens %s", modsAndSource);
+                    if (obj.isQualified())
+                        formatCommaList(ostream, " to", obj.targets());
+                    else
+                        ostream.println();
                 }
+
+                // non-exported/non-open packages
+                Set<String> concealed = new TreeSet<>(md.packages());
+                md.exports().stream().map(Exports::source).forEach(concealed::remove);
+                md.opens().stream().map(Opens::source).forEach(concealed::remove);
+                concealed.forEach(p -> ostream.format("  contains %s%n", p));
             }
         }
     }
 
+    static <T> String toString(Set<T> s) {
+        return toStringStream(s).collect(Collectors.joining(" "));
+    }
+
+    static <T> Stream<String> toStringStream(Set<T> s) {
+        return s.stream().map(e -> e.toString().toLowerCase());
+    }
+
     static String midAndLocation(ModuleDescriptor md, Optional<URI> location ) {
         URI loc = location.orElse(null);
         if (loc == null || loc.getScheme().equalsIgnoreCase("jrt"))
diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
index f66bfa9..4fd4346 100644
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties
@@ -28,8 +28,8 @@
 \           (to execute a class)\n   or  {0} [options] -jar jarfile [args...]\n\
 \           (to execute a jar file)\n\
 \   or  {0} [options] -p <modulepath> -m <modulename>[/<mainclass>] [args...]\n\
-\           (to execute the main class in a module)\n\
-where options include:\n
+\           (to execute the main class in a module)\n\n\
+where options include:\n\n
 
 java.launcher.opt.datamodel  =\    -d{0}\t  Deprecated, will be removed in a future release\n
 java.launcher.opt.vmselect   =\    {0}\t  to select the "{1}" VM\n
@@ -68,11 +68,16 @@
 \                  set a system property\n\
 \    -verbose:[class|gc|jni]\n\
 \                  enable verbose output\n\
-\    -version      print product version and exit\n\
-\    -showversion  print product version and continue\n\
-\    -? -help --help\n\
-\                  print this help message\n\
-\    -X            print help on non-standard options\n\
+\    -version      print product version to the error stream and exit\n\
+\    --version     print product version to the output stream and exit\n\
+\    -showversion  print product version to the error stream and continue\n\
+\    --show-version\n\
+\                  print product version to the output stream and continue\n\
+\    -? -h -help\n\
+\                  print this help message to the error stream\n\
+\    --help        print this help message to the output stream\n\
+\    -X            print help on extra options to the error stream\n\
+\    --help-extra  print help on extra options to the output stream\n\
 \    -ea[:<packagename>...|:<classname>]\n\
 \    -enableassertions[:<packagename>...|:<classname>]\n\
 \                  enable assertions with specified granularity\n\
@@ -98,14 +103,12 @@
 \                  The most appropriate scaled image provided will be picked up\n\
 \                  automatically.\n\
 \                  See the SplashScreen API documentation for more information.\n\
-\    @<filepath>   read options from the specified file\n\
+\    @<filepath>   read options from the specified file\n\n\
 \To specify an argument for a long option, you can use --<name>=<value> or\n\
-\--<name> <value>.\n\
-
-See http://www.oracle.com/technetwork/java/javase/documentation/index.html for more details.
+\--<name> <value>.\n
 
 # Translators please note do not translate the options themselves
-java.launcher.X.usage=\
+java.launcher.X.usage=\n\
 \    -Xbatch           disable background compilation\n\
 \    -Xbootclasspath/a:<directories and zip/jar files separated by {0}>\n\
 \                      append to end of bootstrap class path\n\
@@ -152,10 +155,13 @@
 \                      regardless of module declaration.\n\
 \                      <target-module> can be ALL-UNNAMED to export to all\n\
 \                      unnamed modules.\n\
+\    --add-opens <module>/<package>=<target-module>(,<target-module>)*\n\
+\                      updates <module> to open <package> to\n\
+\                      <target-module>, regardless of module declaration.\n\
 \    --patch-module <module>=<file>({0}<file>)*\n\
 \                      Override or augment a module with classes and resources\n\
 \                      in JAR files or directories.\n\n\
-These options are non-standard and subject to change without notice.\n
+These extra options are subject to change without notice.\n
 
 # Translators please note do not translate the options themselves
 java.launcher.X.macosx.usage=\
diff --git a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java
index 580842b..9237d37 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.net.*;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.Properties;
 import sun.net.NetworkClient;
 import sun.net.ProgressSource;
@@ -35,6 +36,7 @@
 import sun.net.www.HeaderParser;
 import sun.net.www.MeteredStream;
 import sun.net.www.ParseUtil;
+import sun.net.www.protocol.http.AuthenticatorKeys;
 import sun.net.www.protocol.http.HttpURLConnection;
 import sun.util.logging.PlatformLogger;
 import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
@@ -132,6 +134,8 @@
         }
     }
 
+    protected volatile String authenticatorKey;
+
     /**
      * A NOP method kept for backwards binary compatibility
      * @deprecated -- system properties are no longer cached.
@@ -279,10 +283,12 @@
                     ret = null;
                 }
             }
-
             if (ret != null) {
-                if ((ret.proxy != null && ret.proxy.equals(p)) ||
-                    (ret.proxy == null && p == null)) {
+                String ak = httpuc == null ? AuthenticatorKeys.DEFAULT
+                     : httpuc.getAuthenticatorKey();
+                boolean compatible = Objects.equals(ret.proxy, p)
+                     && Objects.equals(ret.getAuthenticatorKey(), ak);
+                if (compatible) {
                     synchronized (ret) {
                         ret.cachedHttpClient = true;
                         assert ret.inCache;
@@ -306,6 +312,9 @@
         }
         if (ret == null) {
             ret = new HttpClient(url, p, to);
+            if (httpuc != null) {
+                ret.authenticatorKey = httpuc.getAuthenticatorKey();
+            }
         } else {
             SecurityManager security = System.getSecurityManager();
             if (security != null) {
@@ -341,6 +350,12 @@
             to, useCache, httpuc);
     }
 
+    public final String getAuthenticatorKey() {
+        String k = authenticatorKey;
+        if (k == null) return AuthenticatorKeys.DEFAULT;
+        return k;
+    }
+
     /* return it to the cache as still usable, if:
      * 1) It's keeping alive, AND
      * 2) It still has some connections left, AND
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthCache.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthCache.java
index 6af6dd6..5ca44fa 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthCache.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthCache.java
@@ -38,7 +38,8 @@
     /**
      * Put an entry in the cache. pkey is a string specified as follows:
      *
-     * A:[B:]C:D:E[:F]   Between 4 and 6 fields separated by ":"
+     * A:[B:]C:D:E[:F][;key=value]   Between 4 and 6 fields separated by ":",
+     *          and an optional semicolon-separated key=value list postfix,
      *          where the fields have the following meaning:
      * A is "s" or "p" for server or proxy authentication respectively
      * B is optional and is the {@link AuthScheme}, e.g. BASIC, DIGEST, NTLM, etc
@@ -47,6 +48,11 @@
      * E is the port number
      * F is optional and if present is the realm
      *
+     * The semi-colon separated key=value list postfix can be used to
+     * provide additional contextual information, thus allowing
+     * to separate AuthCacheValue instances obtained from different
+     * contexts.
+     *
      * Generally, two entries are created for each AuthCacheValue,
      * one including the realm and one without the realm.
      * Also, for some schemes (digest) multiple entries may be created
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java
index 487e17e..7d0dae9 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 import java.net.PasswordAuthentication;
 import java.net.URL;
 import java.util.HashMap;
+import java.util.Objects;
 
 import sun.net.www.HeaderParser;
 
@@ -190,8 +191,18 @@
     /** The shortest path from the URL we authenticated against. */
     String path;
 
+    /**
+     * A key identifying the authenticator from which the credentials
+     * were obtained.
+     * {@link AuthenticatorKeys#DEFAULT} identifies the {@linkplain
+     * java.net.Authenticator#setDefault(java.net.Authenticator) default}
+     * authenticator.
+     */
+     String authenticatorKey;
+
     /** Use this constructor only for proxy entries */
-    public AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
+    public AuthenticationInfo(char type, AuthScheme authScheme, String host,
+                              int port, String realm, String authenticatorKey) {
         this.type = type;
         this.authScheme = authScheme;
         this.protocol = "";
@@ -199,6 +210,7 @@
         this.port = port;
         this.realm = realm;
         this.path = null;
+        this.authenticatorKey = Objects.requireNonNull(authenticatorKey);
     }
 
     public Object clone() {
@@ -214,7 +226,8 @@
      * Constructor used to limit the authorization to the path within
      * the URL. Use this constructor for origin server entries.
      */
-    public AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
+    public AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm,
+                              String authenticatorKey) {
         this.type = type;
         this.authScheme = authScheme;
         this.protocol = url.getProtocol().toLowerCase();
@@ -231,7 +244,16 @@
         else {
             this.path = reducePath (urlPath);
         }
+        this.authenticatorKey = Objects.requireNonNull(authenticatorKey);
+    }
 
+    /**
+     * The {@linkplain java.net.Authenticator#getKey(java.net.Authenticator) key}
+     * of the authenticator that was used to obtain the credentials.
+     * @return The authenticator's key.
+     */
+    public final String getAuthenticatorKey() {
+        return authenticatorKey;
     }
 
     /*
@@ -256,13 +278,14 @@
      * don't yet know the realm
      * (i.e. when we're preemptively setting the auth).
      */
-    static AuthenticationInfo getServerAuth(URL url) {
+    static AuthenticationInfo getServerAuth(URL url, String authenticatorKey) {
         int port = url.getPort();
         if (port == -1) {
             port = url.getDefaultPort();
         }
         String key = SERVER_AUTHENTICATION + ":" + url.getProtocol().toLowerCase()
-                + ":" + url.getHost().toLowerCase() + ":" + port;
+                + ":" + url.getHost().toLowerCase() + ":" + port
+                + ";auth=" + authenticatorKey;
         return getAuth(key, url);
     }
 
@@ -272,13 +295,17 @@
      * In this case we do not use the path because the protection space
      * is identified by the host:port:realm only
      */
-    static String getServerAuthKey(URL url, String realm, AuthScheme scheme) {
+    static String getServerAuthKey(URL url, String realm, AuthScheme scheme,
+                                   String authenticatorKey) {
         int port = url.getPort();
         if (port == -1) {
             port = url.getDefaultPort();
         }
-        String key = SERVER_AUTHENTICATION + ":" + scheme + ":" + url.getProtocol().toLowerCase()
-                     + ":" + url.getHost().toLowerCase() + ":" + port + ":" + realm;
+        String key = SERVER_AUTHENTICATION + ":" + scheme + ":"
+                     + url.getProtocol().toLowerCase()
+                     + ":" + url.getHost().toLowerCase()
+                     + ":" + port + ":" + realm
+                     + ";auth=" + authenticatorKey;
         return key;
     }
 
@@ -309,8 +336,10 @@
      * for preemptive header-setting. Note, the protocol field is always
      * blank for proxies.
      */
-    static AuthenticationInfo getProxyAuth(String host, int port) {
-        String key = PROXY_AUTHENTICATION + "::" + host.toLowerCase() + ":" + port;
+    static AuthenticationInfo getProxyAuth(String host, int port,
+                                           String authenticatorKey) {
+        String key = PROXY_AUTHENTICATION + "::" + host.toLowerCase() + ":" + port
+                     + ";auth=" + authenticatorKey;
         AuthenticationInfo result = (AuthenticationInfo) cache.get(key, null);
         return result;
     }
@@ -320,9 +349,12 @@
      * Used in response to a challenge. Note, the protocol field is always
      * blank for proxies.
      */
-    static String getProxyAuthKey(String host, int port, String realm, AuthScheme scheme) {
-        String key = PROXY_AUTHENTICATION + ":" + scheme + "::" + host.toLowerCase()
-                        + ":" + port + ":" + realm;
+    static String getProxyAuthKey(String host, int port, String realm,
+                                  AuthScheme scheme, String authenticatorKey) {
+        String key = PROXY_AUTHENTICATION + ":" + scheme
+                        + "::" + host.toLowerCase()
+                        + ":" + port + ":" + realm
+                        + ";auth=" + authenticatorKey;
         return key;
     }
 
@@ -424,27 +456,34 @@
     String cacheKey(boolean includeRealm) {
         // This must be kept in sync with the getXXXAuth() methods in this
         // class.
+        String authenticatorKey = getAuthenticatorKey();
         if (includeRealm) {
             return type + ":" + authScheme + ":" + protocol + ":"
-                        + host + ":" + port + ":" + realm;
+                        + host + ":" + port + ":" + realm
+                     + ";auth=" + authenticatorKey;
         } else {
-            return type + ":" + protocol + ":" + host + ":" + port;
+            return type + ":" + protocol + ":" + host + ":" + port
+                     + ";auth=" + authenticatorKey;
         }
     }
 
     String s1, s2;  /* used for serialization of pw */
 
-    private void readObject(ObjectInputStream s)
+    private synchronized void readObject(ObjectInputStream s)
         throws IOException, ClassNotFoundException
     {
         s.defaultReadObject ();
         pw = new PasswordAuthentication (s1, s2.toCharArray());
         s1 = null; s2= null;
+        if (authenticatorKey == null) {
+            authenticatorKey = AuthenticatorKeys.DEFAULT;
+        }
     }
 
     private synchronized void writeObject(java.io.ObjectOutputStream s)
         throws IOException
     {
+        Objects.requireNonNull(authenticatorKey);
         s1 = pw.getUserName();
         s2 = new String (pw.getPassword());
         s.defaultWriteObject ();
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticatorKeys.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticatorKeys.java
new file mode 100644
index 0000000..3ae256c
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticatorKeys.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.www.protocol.http;
+
+import java.net.Authenticator;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ *  A class used to tie a key to an authenticator instance.
+ */
+public final class AuthenticatorKeys {
+    private AuthenticatorKeys() {
+        throw new InternalError("Trying to instantiate static class");
+    }
+
+    public static final String DEFAULT = "default";
+    private static final AtomicLong IDS = new AtomicLong();
+
+    public static String computeKey(Authenticator a) {
+        return System.identityHashCode(a) + "-" + IDS.incrementAndGet()
+               + "@" + a.getClass().getName();
+    }
+
+    /**
+     * Returns a key for the given authenticator.
+     *
+     * @param authenticator The authenticator; {@code null} should be
+     *        passed when the {@linkplain
+     *        Authenticator#setDefault(java.net.Authenticator) default}
+     *        authenticator is meant.
+     * @return A key for the given authenticator, {@link #DEFAULT} for
+     *         {@code null}.
+     */
+    public static String getKey(Authenticator authenticator) {
+        if (authenticator == null) {
+            return DEFAULT;
+        }
+        return authenticatorKeyAccess.getKey(authenticator);
+    }
+
+    @FunctionalInterface
+    public interface AuthenticatorKeyAccess {
+        public String getKey(Authenticator a);
+    }
+
+    private static AuthenticatorKeyAccess authenticatorKeyAccess;
+    public static void setAuthenticatorKeyAccess(AuthenticatorKeyAccess access) {
+        if (authenticatorKeyAccess == null && access != null) {
+            authenticatorKeyAccess = access;
+        }
+    }
+
+}
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java
index e77da61..db2e880 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Base64;
+import java.util.Objects;
 import sun.net.www.HeaderParser;
 
 /**
@@ -54,9 +55,11 @@
      * Create a BasicAuthentication
      */
     public BasicAuthentication(boolean isProxy, String host, int port,
-                               String realm, PasswordAuthentication pw) {
+                               String realm, PasswordAuthentication pw,
+                               String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              AuthScheme.BASIC, host, port, realm);
+              AuthScheme.BASIC, host, port, realm,
+              Objects.requireNonNull(authenticatorKey));
         String plain = pw.getUserName() + ":";
         byte[] nameBytes = null;
         try {
@@ -84,9 +87,11 @@
      * Create a BasicAuthentication
      */
     public BasicAuthentication(boolean isProxy, String host, int port,
-                               String realm, String auth) {
+                               String realm, String auth,
+                               String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              AuthScheme.BASIC, host, port, realm);
+              AuthScheme.BASIC, host, port, realm,
+              Objects.requireNonNull(authenticatorKey));
         this.auth = "Basic " + auth;
     }
 
@@ -94,9 +99,11 @@
      * Create a BasicAuthentication
      */
     public BasicAuthentication(boolean isProxy, URL url, String realm,
-                                   PasswordAuthentication pw) {
+                               PasswordAuthentication pw,
+                               String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              AuthScheme.BASIC, url, realm);
+              AuthScheme.BASIC, url, realm,
+              Objects.requireNonNull(authenticatorKey));
         String plain = pw.getUserName() + ":";
         byte[] nameBytes = null;
         try {
@@ -124,9 +131,10 @@
      * Create a BasicAuthentication
      */
     public BasicAuthentication(boolean isProxy, URL url, String realm,
-                                   String auth) {
+                               String auth, String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              AuthScheme.BASIC, url, realm);
+              AuthScheme.BASIC, url, realm,
+              Objects.requireNonNull(authenticatorKey));
         this.auth = "Basic " + auth;
     }
 
@@ -202,4 +210,3 @@
         return npath;
     }
 }
-
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java
index 32fe64c..7d49792 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java
@@ -38,6 +38,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivilegedAction;
 import java.security.AccessController;
+import java.util.Objects;
 import static sun.net.www.protocol.http.HttpURLConnection.HTTP_CONNECT;
 
 /**
@@ -193,11 +194,12 @@
      */
     public DigestAuthentication(boolean isProxy, URL url, String realm,
                                 String authMethod, PasswordAuthentication pw,
-                                Parameters params) {
+                                Parameters params, String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
               AuthScheme.DIGEST,
               url,
-              realm);
+              realm,
+              Objects.requireNonNull(authenticatorKey));
         this.authMethod = authMethod;
         this.pw = pw;
         this.params = params;
@@ -205,12 +207,13 @@
 
     public DigestAuthentication(boolean isProxy, String host, int port, String realm,
                                 String authMethod, PasswordAuthentication pw,
-                                Parameters params) {
+                                Parameters params, String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
               AuthScheme.DIGEST,
               host,
               port,
-              realm);
+              realm,
+              Objects.requireNonNull(authenticatorKey));
         this.authMethod = authMethod;
         this.pw = pw;
         this.params = params;
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java
index 9537275..038f7ad 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpCallerInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 package sun.net.www.protocol.http;
 
+import java.net.Authenticator;
 import java.net.Authenticator.RequestorType;
 import java.net.InetAddress;
 import java.net.URL;
@@ -49,6 +50,7 @@
     public final int port;
     public final InetAddress addr;
     public final RequestorType authType;
+    public final Authenticator authenticator;
 
     /**
      * Create a schemed object based on an un-schemed one.
@@ -62,12 +64,13 @@
         this.addr = old.addr;
         this.authType = old.authType;
         this.scheme = scheme;
+        this.authenticator =  old.authenticator;
     }
 
     /**
      * Constructor an un-schemed object for site access.
      */
-    public HttpCallerInfo(URL url) {
+    public HttpCallerInfo(URL url, Authenticator a) {
         this.url= url;
         prompt = "";
         host = url.getHost();
@@ -90,12 +93,13 @@
         protocol = url.getProtocol();
         authType = RequestorType.SERVER;
         scheme = "";
+        authenticator = a;
     }
 
     /**
      * Constructor an un-schemed object for proxy access.
      */
-    public HttpCallerInfo(URL url, String host, int port) {
+    public HttpCallerInfo(URL url, String host, int port, Authenticator a) {
         this.url= url;
         this.host = host;
         this.port = port;
@@ -104,5 +108,6 @@
         protocol = url.getProtocol();
         authType = RequestorType.PROXY;
         scheme = "";
+        authenticator = a;
     }
 }
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
index 058de37..5e23b04 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,6 +78,7 @@
 import java.util.TimeZone;
 import java.net.MalformedURLException;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 import java.util.Properties;
 import static sun.net.www.protocol.http.AuthScheme.BASIC;
 import static sun.net.www.protocol.http.AuthScheme.DIGEST;
@@ -304,6 +305,8 @@
     protected HttpClient http;
     protected Handler handler;
     protected Proxy instProxy;
+    protected volatile Authenticator authenticator;
+    protected volatile String authenticatorKey;
 
     private CookieHandler cookieHandler;
     private final ResponseCache cacheHandler;
@@ -433,6 +436,7 @@
      */
     private static PasswordAuthentication
     privilegedRequestPasswordAuthentication(
+                            final Authenticator authenticator,
                             final String host,
                             final InetAddress addr,
                             final int port,
@@ -448,7 +452,7 @@
                         logger.finest("Requesting Authentication: host =" + host + " url = " + url);
                     }
                     PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
-                        host, addr, port, protocol,
+                        authenticator, host, addr, port, protocol,
                         prompt, scheme, url, authType);
                     if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
                         logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
@@ -507,6 +511,22 @@
         this.authObj = authObj;
     }
 
+    @Override
+    public synchronized void setAuthenticator(Authenticator auth) {
+        if (connecting || connected) {
+            throw new IllegalStateException(
+                  "Authenticator must be set before connecting");
+        }
+        authenticator = Objects.requireNonNull(auth);
+        authenticatorKey = AuthenticatorKeys.getKey(authenticator);
+    }
+
+    public String getAuthenticatorKey() {
+        String k = authenticatorKey;
+        if (k == null) return AuthenticatorKeys.getKey(authenticator);
+        return k;
+    }
+
     /*
      * checks the validity of http message header and throws
      * IllegalArgumentException if invalid.
@@ -631,7 +651,8 @@
                 requests.setIfNotSet("If-Modified-Since", fo.format(date));
             }
             // check for preemptive authorization
-            AuthenticationInfo sauth = AuthenticationInfo.getServerAuth(url);
+            AuthenticationInfo sauth = AuthenticationInfo.getServerAuth(url,
+                                             getAuthenticatorKey());
             if (sauth != null && sauth.supportsPreemptiveAuthorization() ) {
                 // Sets "Authorization"
                 requests.setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(url,method));
@@ -800,15 +821,15 @@
      *        if present
      */
     protected void setProxiedClient (URL url,
-                                           String proxyHost, int proxyPort,
-                                           boolean useCache)
+                                     String proxyHost, int proxyPort,
+                                     boolean useCache)
         throws IOException {
         proxiedConnect(url, proxyHost, proxyPort, useCache);
     }
 
     protected void proxiedConnect(URL url,
-                                           String proxyHost, int proxyPort,
-                                           boolean useCache)
+                                  String proxyHost, int proxyPort,
+                                  boolean useCache)
         throws IOException {
         http = HttpClient.New (url, proxyHost, proxyPort, useCache,
             connectTimeout, this);
@@ -878,10 +899,14 @@
         boolean redir;
         int redirects = 0;
         InputStream in;
+        Authenticator a = null;
 
         do {
             if (c instanceof HttpURLConnection) {
                 ((HttpURLConnection) c).setInstanceFollowRedirects(false);
+                if (a == null) {
+                    a = ((HttpURLConnection) c).authenticator;
+                }
             }
 
             // We want to open the input stream before
@@ -912,6 +937,9 @@
                     }
                     redir = true;
                     c = target.openConnection();
+                    if (a != null && c instanceof HttpURLConnection) {
+                        ((HttpURLConnection)c).setAuthenticator(a);
+                    }
                     redirects++;
                 }
             }
@@ -1612,7 +1640,8 @@
                             responses,
                             new HttpCallerInfo(url,
                                                http.getProxyHostUsed(),
-                                               http.getProxyPortUsed()),
+                                               http.getProxyPortUsed(),
+                                               authenticator),
                             dontUseNegotiate,
                             disabledProxyingSchemes
                     );
@@ -1684,7 +1713,7 @@
 
                     srvHdr = new AuthenticationHeader (
                             "WWW-Authenticate", responses,
-                            new HttpCallerInfo(url),
+                            new HttpCallerInfo(url, authenticator),
                             dontUseNegotiate
                     );
 
@@ -1762,7 +1791,8 @@
                                 /* path could be an abs_path or a complete URI */
                                 URL u = new URL (url, path);
                                 DigestAuthentication d = new DigestAuthentication (
-                                                   false, u, realm, "Digest", pw, digestparams);
+                                                   false, u, realm, "Digest", pw,
+                                                   digestparams, srv.authenticatorKey);
                                 d.addToCache ();
                             } catch (Exception e) {}
                         }
@@ -2065,7 +2095,8 @@
                             responses,
                             new HttpCallerInfo(url,
                                                http.getProxyHostUsed(),
-                                               http.getProxyPortUsed()),
+                                               http.getProxyPortUsed(),
+                                               authenticator),
                             dontUseNegotiate,
                             disabledTunnelingSchemes
                     );
@@ -2174,7 +2205,8 @@
     private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOException {
         AuthenticationInfo pauth
             = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
-                                              http.getProxyPortUsed());
+                                              http.getProxyPortUsed(),
+                                              getAuthenticatorKey());
         if (pauth != null && pauth.supportsPreemptiveAuthorization()) {
             String value;
             if (pauth instanceof DigestAuthentication) {
@@ -2228,7 +2260,8 @@
 
             if (realm == null)
                 realm = "";
-            proxyAuthKey = AuthenticationInfo.getProxyAuthKey(host, port, realm, authScheme);
+            proxyAuthKey = AuthenticationInfo.getProxyAuthKey(host, port, realm,
+                                authScheme, getAuthenticatorKey());
             ret = AuthenticationInfo.getProxyAuth(proxyAuthKey);
             if (ret == null) {
                 switch (authScheme) {
@@ -2248,21 +2281,25 @@
                     }
                     PasswordAuthentication a =
                         privilegedRequestPasswordAuthentication(
+                                    authenticator,
                                     host, addr, port, "http",
                                     realm, scheme, url, RequestorType.PROXY);
                     if (a != null) {
-                        ret = new BasicAuthentication(true, host, port, realm, a);
+                        ret = new BasicAuthentication(true, host, port, realm, a,
+                                             getAuthenticatorKey());
                     }
                     break;
                 case DIGEST:
                     a = privilegedRequestPasswordAuthentication(
+                                    authenticator,
                                     host, null, port, url.getProtocol(),
                                     realm, scheme, url, RequestorType.PROXY);
                     if (a != null) {
                         DigestAuthentication.Parameters params =
                             new DigestAuthentication.Parameters();
                         ret = new DigestAuthentication(true, host, port, realm,
-                                                            scheme, a, params);
+                                             scheme, a, params,
+                                             getAuthenticatorKey());
                     }
                     break;
                 case NTLM:
@@ -2288,6 +2325,7 @@
                             logger.finest("Trying Transparent NTLM authentication");
                         } else {
                             a = privilegedRequestPasswordAuthentication(
+                                                authenticator,
                                                 host, null, port, url.getProtocol(),
                                                 "", scheme, url, RequestorType.PROXY);
                         }
@@ -2299,7 +2337,8 @@
                         */
                         if (tryTransparentNTLMProxy ||
                               (!tryTransparentNTLMProxy && a != null)) {
-                            ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a);
+                            ret = NTLMAuthenticationProxy.proxy.create(true, host,
+                                    port, a, getAuthenticatorKey());
                         }
 
                         /* set to false so that we do not try again */
@@ -2330,7 +2369,8 @@
                     URL u = new URL("http", host, port, "/");
                     String a = defaultAuth.authString(u, scheme, realm);
                     if (a != null) {
-                        ret = new BasicAuthentication (true, host, port, realm, a);
+                        ret = new BasicAuthentication (true, host, port, realm, a,
+                                  getAuthenticatorKey());
                         // not in cache by default - cache on success
                     }
                 } catch (java.net.MalformedURLException ignored) {
@@ -2383,7 +2423,8 @@
             domain = p.findValue ("domain");
             if (realm == null)
                 realm = "";
-            serverAuthKey = AuthenticationInfo.getServerAuthKey(url, realm, authScheme);
+            serverAuthKey = AuthenticationInfo.getServerAuthKey(url, realm, authScheme,
+                                               getAuthenticatorKey());
             ret = AuthenticationInfo.getServerAuth(serverAuthKey);
             InetAddress addr = null;
             if (ret == null) {
@@ -2409,19 +2450,24 @@
                 case BASIC:
                     PasswordAuthentication a =
                         privilegedRequestPasswordAuthentication(
+                            authenticator,
                             url.getHost(), addr, port, url.getProtocol(),
                             realm, scheme, url, RequestorType.SERVER);
                     if (a != null) {
-                        ret = new BasicAuthentication(false, url, realm, a);
+                        ret = new BasicAuthentication(false, url, realm, a,
+                                    getAuthenticatorKey());
                     }
                     break;
                 case DIGEST:
                     a = privilegedRequestPasswordAuthentication(
+                            authenticator,
                             url.getHost(), addr, port, url.getProtocol(),
                             realm, scheme, url, RequestorType.SERVER);
                     if (a != null) {
                         digestparams = new DigestAuthentication.Parameters();
-                        ret = new DigestAuthentication(false, url, realm, scheme, a, digestparams);
+                        ret = new DigestAuthentication(false, url, realm, scheme,
+                                    a, digestparams,
+                                    getAuthenticatorKey());
                     }
                     break;
                 case NTLM:
@@ -2452,6 +2498,7 @@
                             logger.finest("Trying Transparent NTLM authentication");
                         } else {
                             a = privilegedRequestPasswordAuthentication(
+                                authenticator,
                                 url.getHost(), addr, port, url.getProtocol(),
                                 "", scheme, url, RequestorType.SERVER);
                         }
@@ -2464,7 +2511,8 @@
                          */
                         if (tryTransparentNTLMServer ||
                               (!tryTransparentNTLMServer && a != null)) {
-                            ret = NTLMAuthenticationProxy.proxy.create(false, url1, a);
+                            ret = NTLMAuthenticationProxy.proxy.create(false,
+                                     url1, a, getAuthenticatorKey());
                         }
 
                         /* set to false so that we do not try again */
@@ -2488,7 +2536,8 @@
                 && defaultAuth.schemeSupported(scheme)) {
                 String a = defaultAuth.authString(url, scheme, realm);
                 if (a != null) {
-                    ret = new BasicAuthentication (false, url, realm, a);
+                    ret = new BasicAuthentication (false, url, realm, a,
+                                    getAuthenticatorKey());
                     // not in cache by default - cache on success
                 }
             }
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java
index 335670e..d7961a3 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,21 +45,22 @@
     static final boolean supported = proxy != null ? true : false;
     static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth() : false;
 
-    private final Constructor<? extends AuthenticationInfo> threeArgCtr;
-    private final Constructor<? extends AuthenticationInfo> fiveArgCtr;
+    private final Constructor<? extends AuthenticationInfo> fourArgCtr;
+    private final Constructor<? extends AuthenticationInfo> sixArgCtr;
 
-    private NTLMAuthenticationProxy(Constructor<? extends AuthenticationInfo> threeArgCtr,
-                                    Constructor<? extends AuthenticationInfo> fiveArgCtr) {
-        this.threeArgCtr = threeArgCtr;
-        this.fiveArgCtr = fiveArgCtr;
+    private NTLMAuthenticationProxy(Constructor<? extends AuthenticationInfo> fourArgCtr,
+                                    Constructor<? extends AuthenticationInfo> sixArgCtr) {
+        this.fourArgCtr = fourArgCtr;
+        this.sixArgCtr = sixArgCtr;
     }
 
 
     AuthenticationInfo create(boolean isProxy,
                               URL url,
-                              PasswordAuthentication pw) {
+                              PasswordAuthentication pw,
+                              String authenticatorKey) {
         try {
-            return threeArgCtr.newInstance(isProxy, url, pw);
+            return fourArgCtr.newInstance(isProxy, url, pw, authenticatorKey);
         } catch (ReflectiveOperationException roe) {
             finest(roe);
         }
@@ -70,9 +71,10 @@
     AuthenticationInfo create(boolean isProxy,
                               String host,
                               int port,
-                              PasswordAuthentication pw) {
+                              PasswordAuthentication pw,
+                              String authenticatorKey) {
         try {
-            return fiveArgCtr.newInstance(isProxy, host, port, pw);
+            return sixArgCtr.newInstance(isProxy, host, port, pw, authenticatorKey);
         } catch (ReflectiveOperationException roe) {
             finest(roe);
         }
@@ -115,21 +117,23 @@
     @SuppressWarnings("unchecked")
     private static NTLMAuthenticationProxy tryLoadNTLMAuthentication() {
         Class<? extends AuthenticationInfo> cl;
-        Constructor<? extends AuthenticationInfo> threeArg, fiveArg;
+        Constructor<? extends AuthenticationInfo> fourArg, sixArg;
         try {
             cl = (Class<? extends AuthenticationInfo>)Class.forName(clazzStr, true, null);
             if (cl != null) {
-                threeArg = cl.getConstructor(boolean.class,
+                fourArg = cl.getConstructor(boolean.class,
                                              URL.class,
-                                             PasswordAuthentication.class);
-                fiveArg = cl.getConstructor(boolean.class,
+                                             PasswordAuthentication.class,
+                                             String.class);
+                sixArg = cl.getConstructor(boolean.class,
                                             String.class,
                                             int.class,
-                                            PasswordAuthentication.class);
+                                            PasswordAuthentication.class,
+                                            String.class);
                 supportsTA = cl.getDeclaredMethod(supportsTAStr);
                 isTrustedSite = cl.getDeclaredMethod(isTrustedSiteStr, java.net.URL.class);
-                return new NTLMAuthenticationProxy(threeArg,
-                                                   fiveArg);
+                return new NTLMAuthenticationProxy(fourArg,
+                                                   sixArg);
             }
         } catch (ClassNotFoundException cnfe) {
             finest(cnfe);
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
index 820f3ed..d7c379f 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,8 @@
         super(RequestorType.PROXY==hci.authType ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
               hci.scheme.equalsIgnoreCase("Negotiate") ? NEGOTIATE : KERBEROS,
               hci.url,
-              "");
+              "",
+              AuthenticatorKeys.getKey(hci.authenticator));
         this.hci = hci;
     }
 
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
index eadd290..6283230 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
 import java.net.Proxy;
 import java.security.Principal;
 import java.security.cert.*;
+import java.util.Objects;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -46,6 +47,7 @@
 
 import javax.net.ssl.*;
 import sun.net.www.http.HttpClient;
+import sun.net.www.protocol.http.AuthenticatorKeys;
 import sun.net.www.protocol.http.HttpURLConnection;
 import sun.security.action.*;
 
@@ -334,8 +336,12 @@
             }
 
             if (ret != null) {
-                if ((ret.proxy != null && ret.proxy.equals(p)) ||
-                    (ret.proxy == null && p == Proxy.NO_PROXY)) {
+                String ak = httpuc == null ? AuthenticatorKeys.DEFAULT
+                     : httpuc.getAuthenticatorKey();
+                boolean compatible = ((ret.proxy != null && ret.proxy.equals(p)) ||
+                    (ret.proxy == null && p == Proxy.NO_PROXY))
+                     && Objects.equals(ret.getAuthenticatorKey(), ak);
+                if (compatible) {
                     synchronized (ret) {
                         ret.cachedHttpClient = true;
                         assert ret.inCache;
@@ -364,6 +370,9 @@
         }
         if (ret == null) {
             ret = new HttpsClient(sf, url, p, connectTimeout);
+            if (httpuc != null) {
+                ret.authenticatorKey = httpuc.getAuthenticatorKey();
+            }
         } else {
             SecurityManager security = System.getSecurityManager();
             if (security != null) {
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
index 4290798..1b2a584 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
 import java.net.Proxy;
 import java.net.ProtocolException;
 import java.io.*;
+import java.net.Authenticator;
 import javax.net.ssl.*;
 import java.security.Permission;
 import java.security.Principal;
@@ -517,4 +518,9 @@
     public void setChunkedStreamingMode (int chunklen) {
         delegate.setChunkedStreamingMode(chunklen);
     }
+
+    @Override
+    public void setAuthenticator(Authenticator auth) {
+        delegate.setAuthenticator(auth);
+    }
 }
diff --git a/jdk/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java b/jdk/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java
index cd4061b..c7be9f2 100644
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,8 +64,9 @@
     // invalid, the parser should flag an error in accordance
     // with its logic.
 
-    private char[] input; // the input signature
-    private int index = 0; // index into the input
+    private String input; // the input signature
+    private int index;    // index into the input
+    private int mark;     // index of mark
     // used to mark end of input
     private static final char EOI = ':';
     private static final boolean DEBUG = false;
@@ -73,6 +74,12 @@
     // private constructor - enforces use of static factory
     private SignatureParser(){}
 
+    // prepares parser for new parsing session
+    private void init(String s) {
+        input = s;
+        mark = index = 0;
+    }
+
     // Utility methods.
 
     // Most parsing routines use the following routines to access the
@@ -80,39 +87,32 @@
     // This makes it easy to adapt the parser to operate on streams
     // of various kinds as well as strings.
 
-    // returns current element of the input and advances the input
-    private char getNext(){
-        assert(index <= input.length);
-        try {
-            return input[index++];
-        } catch (ArrayIndexOutOfBoundsException e) { return EOI;}
-    }
-
     // returns current element of the input
     private char current(){
-        assert(index <= input.length);
-        try {
-            return input[index];
-        } catch (ArrayIndexOutOfBoundsException e) { return EOI;}
+        assert(index <= input.length());
+        return index < input.length() ? input.charAt(index) : EOI;
     }
 
     // advance the input
     private void advance(){
-        assert(index <= input.length);
-        index++;
+        assert(index <= input.length());
+        if (index < input.length()) index++;
+    }
+
+    // mark current position
+    private void mark() {
+        mark = index;
     }
 
     // For debugging, prints current character to the end of the input.
     private String remainder() {
-        return new String(input, index, input.length-index);
+        return input.substring(index);
     }
 
-    // Match c against a "set" of characters
-    private boolean matches(char c, char... set) {
-        for (char e : set) {
-            if (c == e) return true;
-        }
-        return false;
+    // returns a substring of input from mark (inclusive)
+    // to current position (exclusive)
+    private String markToCurrent() {
+        return input.substring(mark, index);
     }
 
     // Error handling routine. Encapsulates error handling.
@@ -152,7 +152,7 @@
      */
     public ClassSignature parseClassSig(String s) {
         if (DEBUG) System.out.println("Parsing class sig:" + s);
-        input = s.toCharArray();
+        init(s);
         return parseClassSignature();
     }
 
@@ -167,7 +167,7 @@
      */
     public MethodTypeSignature parseMethodSig(String s) {
         if (DEBUG) System.out.println("Parsing method sig:" + s);
-        input = s.toCharArray();
+        init(s);
         return parseMethodTypeSignature();
     }
 
@@ -184,13 +184,13 @@
      */
     public TypeSignature parseTypeSig(String s) {
         if (DEBUG) System.out.println("Parsing type sig:" + s);
-        input = s.toCharArray();
+        init(s);
         return parseTypeSignature();
     }
 
     // Parsing routines.
     // As a rule, the parsing routines access the input using the
-    // utilities current(), getNext() and/or advance().
+    // utilities current() and advance().
     // The convention is that when a parsing routine is invoked
     // it expects the current input to be the first character it should parse
     // and when it completes parsing, it leaves the input at the first
@@ -251,28 +251,22 @@
         return FormalTypeParameter.make(id, bs);
     }
 
-    private String parseIdentifier(){
-        StringBuilder result = new StringBuilder();
-        while (!Character.isWhitespace(current())) {
-            char c = current();
-            switch(c) {
-            case ';':
-            case '.':
-            case '/':
-            case '[':
-            case ':':
-            case '>':
-            case '<':
-                return result.toString();
-            default:{
-                result.append(c);
-                advance();
-            }
-
-            }
-        }
-        return result.toString();
+    private String parseIdentifier() {
+        mark();
+        skipIdentifier();
+        return markToCurrent();
     }
+
+    private void skipIdentifier() {
+        char c = current();
+        while (c != ';' && c != '.' && c != '/' &&
+               c != '[' && c != ':' && c != '>' &&
+               c != '<' && !Character.isWhitespace(c)) {
+            advance();
+            c = current();
+        }
+    }
+
     /**
      * FieldTypeSignature:
      *     ClassTypeSignature
@@ -325,18 +319,13 @@
         // Parse both any optional leading PackageSpecifier as well as
         // the following SimpleClassTypeSignature.
 
-        String id = parseIdentifier();
-
-        if (current() == '/') { // package name
-            StringBuilder idBuild = new StringBuilder(id);
-
-            while(current() == '/') {
-                advance();
-                idBuild.append(".");
-                idBuild.append(parseIdentifier());
-            }
-            id = idBuild.toString();
+        mark();
+        skipIdentifier();
+        while (current() == '/') {
+            advance();
+            skipIdentifier();
         }
+        String id = markToCurrent().replace('/', '.');
 
         switch (current()) {
         case ';':
@@ -379,11 +368,6 @@
         }
     }
 
-    private TypeArgument[] parseTypeArgumentsOpt() {
-        if (current() == '<') {return parseTypeArguments();}
-        else {return new TypeArgument[0];}
-    }
-
     /**
      * TypeArguments:
      *     "<" TypeArgument+ ">"
diff --git a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
index a4bb681..9055959 100644
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
@@ -324,15 +324,17 @@
 
         PublicKey currPubKey = cert.getPublicKey();
 
-        // Check against DisabledAlgorithmConstraints certpath constraints.
-        // permits() will throw exception on failure.
-        certPathDefaultConstraints.permits(primitives,
+        if (constraints instanceof DisabledAlgorithmConstraints) {
+            // Check against DisabledAlgorithmConstraints certpath constraints.
+            // permits() will throw exception on failure.
+            ((DisabledAlgorithmConstraints)constraints).permits(primitives,
                 new CertConstraintParameters((X509Certificate)cert,
                         trustedMatch, pkixdate, jarTimestamp));
-        // If there is no previous key, set one and exit
-        if (prevPubKey == null) {
-            prevPubKey = currPubKey;
-            return;
+            // If there is no previous key, set one and exit
+            if (prevPubKey == null) {
+                prevPubKey = currPubKey;
+                return;
+            }
         }
 
         X509CertImpl x509Cert;
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java
similarity index 75%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java
index 789cdb9..126286a 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProvider.java
@@ -4,7 +4,9 @@
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
+ * 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
@@ -21,13 +23,7 @@
  * questions.
  */
 
-package p7;
+package sun.security.util;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
-    }
+public interface AuthResourcesProvider extends java.util.spi.ResourceBundleProvider {
 }
diff --git a/jdk/src/java.base/share/classes/java/lang/module/Dependence.java b/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java
similarity index 68%
rename from jdk/src/java.base/share/classes/java/lang/module/Dependence.java
rename to jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java
index 24538c0..6572ad0 100644
--- a/jdk/src/java.base/share/classes/java/lang/module/Dependence.java
+++ b/jdk/src/java.base/share/classes/sun/security/util/AuthResourcesProviderImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,23 +23,13 @@
  * questions.
  */
 
-package java.lang.module;
+package sun.security.util;
 
-import java.util.*;
-import java.util.stream.*;
+import java.util.spi.AbstractResourceBundleProvider;
 
-
-class Dependence {
-
-    private Dependence() { }
-
-    static <T> Stream<String> toStringStream(Set<T> s) {
-        return s.stream().map(e -> e.toString().toLowerCase());
+public final class AuthResourcesProviderImpl extends AbstractResourceBundleProvider
+       implements AuthResourcesProvider {
+    public AuthResourcesProviderImpl() {
+        super("java.class");
     }
-
-    static <M> String toString(Set<M> mods, String what) {
-        return (Stream.concat(toStringStream(mods), Stream.of(what)))
-                      .collect(Collectors.joining(" "));
-    }
-
-}
+}
\ No newline at end of file
diff --git a/jdk/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java b/jdk/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java
new file mode 100644
index 0000000..c8fd888
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/text/spi/JavaTimeDateTimePatternProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package sun.text.spi;
+
+import java.util.Locale;
+import java.util.spi.LocaleServiceProvider;
+
+/**
+ * Service Provider Interface for retrieving DateTime patterns from
+ * specified Locale provider for java.time.
+ */
+
+public abstract class JavaTimeDateTimePatternProvider extends LocaleServiceProvider {
+
+    protected JavaTimeDateTimePatternProvider() {
+    }
+
+    /**
+     * Gets the formatting pattern for a timeStyle
+     * dateStyle, calendarType and locale.
+     * Concrete implementation of this method will retrieve
+     * a java.time specific dateTime Pattern from selected Locale Provider.
+     *
+     * @param timeStyle an {@code int} value representing FormatStyle constant, -1
+     * for date-only pattern
+     * @param dateStyle an {@code int} value,representing FormatStyle constant, -1
+     * for time-only pattern
+     * @param locale {@code locale}, non-null
+     * @param calType a {@code String},non-null representing CalendarType such as "japanese",
+     * "iso8601"
+     * @return  formatting pattern {@code String}
+     * @see java.time.format.DateTimeFormatterBuilder#convertStyle(java.time.format.FormatStyle)
+     * @since 9
+     */
+    public abstract String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale);
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java
index 1963b4d..89cc217 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
 import java.util.spi.TimeZoneNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -156,6 +157,11 @@
         return null;
     }
 
+    @Override
+    public JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
+        return getLocaleServiceProvider(JavaTimeDateTimePatternProvider.class);
+    }
+
     private static Locale[] availableLocales = null;
 
     @Override
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
index c16c012..db17c38 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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
@@ -50,6 +50,7 @@
 import java.util.spi.LocaleNameProvider;
 import java.util.spi.LocaleServiceProvider;
 import java.util.spi.TimeZoneNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.resources.LocaleData;
 import sun.util.spi.CalendarProvider;
 
@@ -109,6 +110,8 @@
             return (P) getCalendarNameProvider();
         case "CalendarProvider":
             return (P) getCalendarProvider();
+        case "JavaTimeDateTimePatternProvider":
+            return (P) getJavaTimeDateTimePatternProvider();
         default:
             throw new InternalError("should not come down here");
         }
@@ -128,6 +131,7 @@
     private volatile CalendarNameProvider calendarNameProvider;
 
     private volatile CalendarProvider calendarProvider;
+    private volatile JavaTimeDateTimePatternProvider javaTimeDateTimePatternProvider;
 
     /*
      * Getter methods for java.text.spi.* providers
@@ -354,6 +358,27 @@
         return calendarProvider;
     }
 
+    /**
+     * Getter methods for sun.text.spi.JavaTimeDateTimePatternProvider provider
+     */
+    @Override
+    public JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
+        if (javaTimeDateTimePatternProvider == null) {
+            JavaTimeDateTimePatternProvider provider = AccessController.doPrivileged(
+                    (PrivilegedAction<JavaTimeDateTimePatternProvider>) ()
+                    -> new JavaTimeDateTimePatternImpl(
+                            getAdapterType(),
+                            getLanguageTagSet("FormatData")));
+
+            synchronized (this) {
+                if (javaTimeDateTimePatternProvider == null) {
+                    javaTimeDateTimePatternProvider = provider;
+                }
+            }
+        }
+        return javaTimeDateTimePatternProvider;
+    }
+
     @Override
     public LocaleResources getLocaleResources(Locale locale) {
         LocaleResources lr = localeResourcesMap.get(locale);
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java
new file mode 100644
index 0000000..41de2dd
--- /dev/null
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JavaTimeDateTimePatternImpl.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.util.locale.provider;
+
+import java.util.Locale;
+import java.util.Set;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
+
+/**
+ * Concrete implementation of the {@link sun.text.spi.JavaTimeDateTimePatternProvider
+ * } class for the JRE LocaleProviderAdapter.
+ *
+ */
+public class JavaTimeDateTimePatternImpl extends JavaTimeDateTimePatternProvider implements AvailableLanguageTags {
+
+    private final LocaleProviderAdapter.Type type;
+    private final Set<String> langtags;
+
+    public JavaTimeDateTimePatternImpl(LocaleProviderAdapter.Type type, Set<String> langtags) {
+        this.type = type;
+        this.langtags = langtags;
+    }
+
+    /**
+     * Returns an array of all locales for which this locale service provider
+     * can provide localized objects or names.
+     *
+     * @return An array of all locales for which this locale service provider
+     * can provide localized objects or names.
+     */
+    @Override
+    public Locale[] getAvailableLocales() {
+        return LocaleProviderAdapter.toLocaleArray(langtags);
+    }
+
+    @Override
+    public boolean isSupportedLocale(Locale locale) {
+        return LocaleProviderAdapter.forType(type).isSupportedProviderLocale(locale, langtags);
+    }
+
+    @Override
+    public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) {
+        LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased().getLocaleResources(locale);
+        String pattern = lr.getJavaTimeDateTimePattern(
+                timeStyle, dateStyle, calType);
+        return pattern;
+
+    }
+
+    @Override
+    public Set<String> getAvailableLanguageTags() {
+        return langtags;
+    }
+}
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
index bafb819..d99b48d 100644
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
@@ -47,6 +47,7 @@
 import java.util.spi.LocaleServiceProvider;
 import java.util.spi.TimeZoneNameProvider;
 import sun.security.action.GetPropertyAction;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -428,6 +429,14 @@
      */
     public abstract CalendarProvider getCalendarProvider();
 
+    /**
+     * Returns a JavaTimeDateTimePatternProvider for this LocaleProviderAdapter,
+     * or null if no JavaTimeDateTimePatternProvider is available.
+     *
+     * @return a JavaTimeDateTimePatternProvider
+     */
+    public abstract JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider();
+
     public abstract LocaleResources getLocaleResources(Locale locale);
 
     public abstract Locale[] getAvailableLocales();
diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/ResourceBundleProviderSupport.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/ResourceBundleProviderSupport.java
deleted file mode 100644
index 114a7fa..0000000
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/ResourceBundleProviderSupport.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.util.locale.provider;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Module;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.PropertyResourceBundle;
-import java.util.ResourceBundle;
-
-/**
- * ResourceBundleProviderSupport provides convenience methods for loading
- * resource bundles.
- */
-public class ResourceBundleProviderSupport {
-    /**
-     * Loads a {@code ResourceBundle} of the given {@code bundleName} local to
-     * the given {@code module}.
-     *
-     * @apiNote
-     * {@link Class#forName(Module, String)} does a stack-based permission check.
-     * Caller of this method is responsible for doing an appropriate permission
-     * on behalf of the caller before calling this method.
-     *
-     * @param module     the module from which the {@code ResourceBundle} is loaded
-     * @param bundleName the bundle name for the {@code ResourceBundle} class,
-     *                   such as "com.example.app.MyResources_fr"
-     * @return the {@code ResourceBundle}, or null if no {@code ResourceBundle} is found
-     * @throws SecurityException
-     *         if a security manager exists, it denies loading the class given by
-     *         {@code bundleName} from the given {@code module}.
-     *         If the given module is "java.base", this method will not do security check.
-     * @throws NullPointerException
-     *         if {@code module} or {@code bundleName) is null
-     * @see Class#forName(Module, String)
-     */
-    public static ResourceBundle loadResourceBundle(Module module, String bundleName)
-    {
-        Class<?> c = Class.forName(module, bundleName);
-        if (c != null && ResourceBundle.class.isAssignableFrom(c)) {
-            try {
-                @SuppressWarnings("unchecked")
-                Class<ResourceBundle> bundleClass = (Class<ResourceBundle>) c;
-                Constructor<ResourceBundle> ctor = bundleClass.getConstructor();
-                if (!Modifier.isPublic(ctor.getModifiers())) {
-                    return null;
-                }
-                // java.base may not be able to read the bundleClass's module.
-                PrivilegedAction<Void> pa1 = () -> { ctor.setAccessible(true); return null; };
-                AccessController.doPrivileged(pa1);
-                try {
-                    return ctor.newInstance((Object[]) null);
-                } catch (InvocationTargetException e) {
-                    uncheckedThrow(e);
-                } catch (InstantiationException | IllegalAccessException e) {
-                    throw new InternalError(e);
-                }
-            } catch (NoSuchMethodException e) {
-            }
-        }
-        return null;
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
-       if (t != null)
-            throw (T)t;
-       else
-            throw new Error("Unknown Exception");
-    }
-
-    /**
-     * Loads properties of the given {@code bundleName} local to the given
-     * {@code module} and returns a {@code ResourceBundle} produced from the
-     * loaded properties.
-     *
-     * @apiNote This method is intended for internal use.  Need to refactor.
-     *
-     * @param module     the module from which the properties are loaded
-     * @param bundleName the bundle name of the properties,
-     *                   such as "com.example.app.MyResources_de"
-     * @return the {@code ResourceBundle} produced from the loaded properties,
-     *         or null if no properties are found
-     * @see PropertyResourceBundle
-     */
-    public static ResourceBundle loadPropertyResourceBundle(Module module, String bundleName)
-            throws IOException
-    {
-        String resourceName = toResourceName(bundleName, "properties");
-        if (resourceName == null) {
-            return null;
-        }
-
-        PrivilegedAction<InputStream> pa = () -> {
-            try {
-                return module.getResourceAsStream(resourceName);
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
-        };
-        try (InputStream stream = AccessController.doPrivileged(pa)) {
-            if (stream != null) {
-                return new PropertyResourceBundle(stream);
-            } else {
-                return null;
-            }
-        } catch (UncheckedIOException e) {
-            throw e.getCause();
-        }
-    }
-
-    private static String toResourceName(String bundleName, String suffix) {
-        if (bundleName.contains("://")) {
-            return null;
-        }
-        StringBuilder sb = new StringBuilder(bundleName.length() + 1 + suffix.length());
-        sb.append(bundleName.replace('.', '/')).append('.').append(suffix);
-        return sb.toString();
-    }
-}
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/Bundles.java b/jdk/src/java.base/share/classes/sun/util/resources/Bundles.java
index 5966bb5..a62f904 100644
--- a/jdk/src/java.base/share/classes/sun/util/resources/Bundles.java
+++ b/jdk/src/java.base/share/classes/sun/util/resources/Bundles.java
@@ -58,8 +58,6 @@
 import java.util.spi.ResourceBundleProvider;
 import jdk.internal.misc.JavaUtilResourceBundleAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.util.locale.provider.ResourceBundleProviderSupport;
-
 
 /**
  */
@@ -203,9 +201,13 @@
                 bundle = loadBundleFromProviders(baseName, targetLocale, providers, cacheKey);
             } else {
                 try {
-                    bundle = ResourceBundleProviderSupport
-                                 .loadResourceBundle(Bundles.class.getModule(),
-                                      strategy.toBundleName(baseName, targetLocale));
+                    String bundleName = strategy.toBundleName(baseName, targetLocale);
+                    Class<?> c = Class.forName(Bundles.class.getModule(), bundleName);
+                    if (c != null && ResourceBundle.class.isAssignableFrom(c)) {
+                        @SuppressWarnings("unchecked")
+                        Class<ResourceBundle> bundleClass = (Class<ResourceBundle>) c;
+                        bundle = bundleAccess.newResourceBundle(bundleClass);
+                    }
                 } catch (Exception e) {
                     cacheKey.setCause(e);
                 }
diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security
index a521dde..fe45e0b 100644
--- a/jdk/src/java.base/share/conf/security/java.security
+++ b/jdk/src/java.base/share/conf/security/java.security
@@ -849,35 +849,35 @@
 #       FFFFFFFF FFFFFFFF, 2}
 
 # Cryptographic Jurisdiction Policy defaults
-# 
+#
 # Due to the import control restrictions of some countries, the default
 # JCE policy files allow for strong but "limited" cryptographic key
 # lengths to be used.  If your country's cryptographic regulations allow,
 # the "unlimited" strength policy files can be used instead, which contain
 # no restrictions on cryptographic strengths.
-# 
+#
 # If your country has restrictions that don't fit either "limited" or
 # "unlimited", an appropriate set of policy files should be created and
 # configured before using this distribution.  The jurisdiction policy file
 # configuration must reflect the cryptographic restrictions appropriate
 # for your country.
-# 
+#
 # YOU ARE ADVISED TO CONSULT YOUR EXPORT/IMPORT CONTROL COUNSEL OR ATTORNEY
 # TO DETERMINE THE EXACT REQUIREMENTS.
-# 
+#
 # The policy files are flat text files organized into subdirectories of
 # <java-home>/conf/security/policy.  Each directory contains a complete
 # set of policy files.
 #
 # The "crypto.policy" Security property controls the directory selection,
 # and thus the effective cryptographic policy.
-# 
-# The default set of directories is:  
-# 
-#     limited | unlimited 
-# 
+#
+# The default set of directories is:
+#
+#     limited | unlimited
+#
 # however other directories can be created and configured.
-# 
+#
 # Within a directory, the effective policy is the combined minimum
 # permissions of the grant statements in the file(s) with the filename
 # pattern "default_*.policy".  At least one grant is required.  For
@@ -891,11 +891,15 @@
 # "exempt_*.policy".  Exemption grants are optional.
 #
 #     limited   =  grants exemption permissions, by which the
-#                  effective policy can be circumvented. 
+#                  effective policy can be circumvented.
 #                  e.g.  KeyRecovery/Escrow/Weakening.
-# 
+#
 # Please see the JCA documentation for additional information on these
 # files and formats.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
 crypto.policy=crypto.policydir-tbd
 
 #
@@ -951,7 +955,8 @@
 #
 # If a pattern includes a "=", it sets a limit.
 # If a limit appears more than once the last value is used.
-# Limits are checked before classes regardless of the order in the sequence of patterns.
+# Limits are checked before classes regardless of the order in the
+# sequence of patterns.
 # If any of the limits are exceeded, the filter status is REJECTED.
 #
 #   maxdepth=value - the maximum depth of a graph
@@ -961,20 +966,24 @@
 #
 # Other patterns, from left to right, match the class or package name as
 # returned from Class.getName.
-# If the class is an array type, the class or package to be matched is the element type.
+# If the class is an array type, the class or package to be matched is the
+# element type.
 # Arrays of any number of dimensions are treated the same as the element type.
 # For example, a pattern of "!example.Foo", rejects creation of any instance or
 # array of example.Foo.
 #
-# If the pattern starts with "!", the status is REJECTED if the remaining pattern
-#   is matched; otherwise the status is ALLOWED if the pattern matches.
-# If the pattern contains "/", the non-empty prefix up to the "/" is the module name;
+# If the pattern starts with "!", the status is REJECTED if the remaining
+# pattern is matched; otherwise the status is ALLOWED if the pattern matches.
+# If the pattern contains "/", the non-empty prefix up to the "/" is the
+# module name;
 #   if the module name matches the module name of the class then
 #   the remaining pattern is matched with the class name.
 #   If there is no "/", the module name is not compared.
-# If the pattern ends with ".**" it matches any class in the package and all subpackages.
+# If the pattern ends with ".**" it matches any class in the package and all
+# subpackages.
 # If the pattern ends with ".*" it matches any class in the package.
-# If the pattern ends with "*", it matches any class with the pattern as a prefix.
+# If the pattern ends with "*", it matches any class with the pattern as a
+# prefix.
 # If the pattern is equal to the class name, it matches.
 # Otherwise, the status is UNDECIDED.
 #
diff --git a/jdk/src/java.base/share/conf/security/policy/README.txt b/jdk/src/java.base/share/conf/security/policy/README.txt
index 84e33c9..3e0e229 100644
--- a/jdk/src/java.base/share/conf/security/policy/README.txt
+++ b/jdk/src/java.base/share/conf/security/policy/README.txt
@@ -10,11 +10,10 @@
 configured via the jurisdiction policy files contained within these
 directories.
 
-Due to import control restrictions of some countries, the default
-JCE policy files bundled in this Java Runtime Environment allow
-for strong but "limited" cryptographic strengths.  For convenience,
-this build also contains the "unlimited strength" policy files which
-contain no restrictions on cryptographic strengths, but they must be
+The default JCE policy files bundled in this Java Runtime Environment
+allow for "unlimited" cryptographic strengths.  For convenience,
+this build also contains the historic "limited" strength policy files
+which contain restrictions on cryptographic strengths, but they must be
 specifically activated by updating the "crypto.policy" Security property
 (e.g. <java-home>/conf/security/java.security) to point to the appropriate
 directory.
diff --git a/jdk/src/java.base/share/native/include/jni.h b/jdk/src/java.base/share/native/include/jni.h
index dc86df3..e29bf04 100644
--- a/jdk/src/java.base/share/native/include/jni.h
+++ b/jdk/src/java.base/share/native/include/jni.h
@@ -770,12 +770,6 @@
 
     jobject (JNICALL *GetModule)
        (JNIEnv* env, jclass clazz);
-
-    void (JNICALL *AddModuleReads)
-        (JNIEnv* env, jobject m1, jobject m2);
-
-    jboolean (JNICALL *CanReadModule)
-        (JNIEnv* env, jobject m1, jobject m2);
 };
 
 /*
@@ -1874,14 +1868,6 @@
         return functions->GetModule(this, clazz);
     }
 
-    void AddModuleReads(jobject m1, jobject m2) {
-        functions->AddModuleReads(this, m1, m2);
-    }
-
-    jboolean CanReadModule(jobject m1, jobject m2) {
-        return functions->CanReadModule(this, m1, m2);
-    }
-
 #endif /* __cplusplus */
 };
 
diff --git a/jdk/src/java.base/share/native/include/jvm.h b/jdk/src/java.base/share/native/include/jvm.h
index 3d7fd391..848fe83 100644
--- a/jdk/src/java.base/share/native/include/jvm.h
+++ b/jdk/src/java.base/share/native/include/jvm.h
@@ -402,8 +402,8 @@
  */
 
 JNIEXPORT void JNICALL
-JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
-                 jobjectArray packages);
+JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
+                 jstring location, jobjectArray packages);
 
 JNIEXPORT void JNICALL
 JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
@@ -411,9 +411,6 @@
 JNIEXPORT void JNICALL
 JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject to_module);
 
-JNIEXPORT jboolean JNICALL
-JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module);
-
 JNIEXPORT void JNICALL
 JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
 
@@ -423,9 +420,6 @@
 JNIEXPORT void JNICALL
 JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
 
-JNIEXPORT jboolean JNICALL
-JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
-
 JNIEXPORT void JNICALL
 JVM_AddModulePackage(JNIEnv* env,  jobject module, jstring package);
 
diff --git a/jdk/src/java.base/share/native/libjava/Module.c b/jdk/src/java.base/share/native/libjava/Module.c
index c31491e..cb6057a 100644
--- a/jdk/src/java.base/share/native/libjava/Module.c
+++ b/jdk/src/java.base/share/native/libjava/Module.c
@@ -30,10 +30,10 @@
 
 JNIEXPORT void JNICALL
 Java_java_lang_reflect_Module_defineModule0(JNIEnv *env, jclass cls, jobject module,
-                                            jstring version, jstring location,
-                                            jobjectArray packages)
+                                            jboolean is_open, jstring version,
+                                            jstring location, jobjectArray packages)
 {
-    JVM_DefineModule(env, module, version, location, packages);
+    JVM_DefineModule(env, module, is_open, version, location, packages);
 }
 
 JNIEXPORT void JNICALL
diff --git a/jdk/src/java.base/share/native/libjli/java.c b/jdk/src/java.base/share/native/libjli/java.c
index 914dbb4..d3f05a6 100644
--- a/jdk/src/java.base/share/native/libjli/java.c
+++ b/jdk/src/java.base/share/native/libjli/java.c
@@ -61,12 +61,13 @@
  * interfaces.
  */
 
-/* we always print to stderr */
-#define USE_STDERR JNI_TRUE
+#define USE_STDERR JNI_TRUE     /* we usually print to stderr */
+#define USE_STDOUT JNI_FALSE
 
 static jboolean printVersion = JNI_FALSE; /* print and exit */
 static jboolean showVersion = JNI_FALSE;  /* print but continue */
 static jboolean printUsage = JNI_FALSE;   /* print and exit*/
+static jboolean printTo = USE_STDERR;     /* where to print version/usage */
 static jboolean printXUsage = JNI_FALSE;  /* print and exit*/
 static jboolean dryRun = JNI_FALSE;       /* initialize VM and exit */
 static char     *showSettings = NULL;     /* print but continue */
@@ -567,6 +568,7 @@
            JLI_StrCmp(name, "--add-modules") == 0 ||
            JLI_StrCmp(name, "--limit-modules") == 0 ||
            JLI_StrCmp(name, "--add-exports") == 0 ||
+           JLI_StrCmp(name, "--add-opens") == 0 ||
            JLI_StrCmp(name, "--add-reads") == 0 ||
            JLI_StrCmp(name, "--patch-module") == 0;
 }
@@ -758,12 +760,15 @@
 
             if (*arg != '-'
                     || JLI_StrCmp(arg, "-version") == 0
+                    || JLI_StrCmp(arg, "--version") == 0
                     || JLI_StrCmp(arg, "-fullversion") == 0
+                    || JLI_StrCmp(arg, "--full-version") == 0
                     || JLI_StrCmp(arg, "-help") == 0
                     || JLI_StrCmp(arg, "--help") == 0
                     || JLI_StrCmp(arg, "-?") == 0
                     || JLI_StrCmp(arg, "-jar") == 0
-                    || JLI_StrCmp(arg, "-X") == 0) {
+                    || JLI_StrCmp(arg, "-X") == 0
+                    || JLI_StrCmp(arg, "--help-extra") == 0) {
                 return;
             }
         }
@@ -1288,6 +1293,7 @@
             } else if (JLI_StrCmp(arg, "--add-modules") == 0 ||
                        JLI_StrCmp(arg, "--limit-modules") == 0 ||
                        JLI_StrCmp(arg, "--add-exports") == 0 ||
+                       JLI_StrCmp(arg, "--add-opens") == 0 ||
                        JLI_StrCmp(arg, "--add-reads") == 0 ||
                        JLI_StrCmp(arg, "--patch-module") == 0) {
                 REPORT_ERROR (has_arg, ARG_ERROR6, arg);
@@ -1295,22 +1301,36 @@
 /*
  * The following cases will cause the argument parsing to stop
  */
-        } else if (JLI_StrCmp(arg, "--help") == 0 ||
-                   JLI_StrCmp(arg, "-help") == 0 ||
+        } else if (JLI_StrCmp(arg, "-help") == 0 ||
                    JLI_StrCmp(arg, "-h") == 0 ||
                    JLI_StrCmp(arg, "-?") == 0) {
             printUsage = JNI_TRUE;
             return JNI_TRUE;
+        } else if (JLI_StrCmp(arg, "--help") == 0) {
+            printUsage = JNI_TRUE;
+            printTo = USE_STDOUT;
+            return JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-version") == 0) {
             printVersion = JNI_TRUE;
             return JNI_TRUE;
+        } else if (JLI_StrCmp(arg, "--version") == 0) {
+            printVersion = JNI_TRUE;
+            printTo = USE_STDOUT;
+            return JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-showversion") == 0) {
             showVersion = JNI_TRUE;
+        } else if (JLI_StrCmp(arg, "--show-version") == 0) {
+            showVersion = JNI_TRUE;
+            printTo = USE_STDOUT;
         } else if (JLI_StrCmp(arg, "--dry-run") == 0) {
             dryRun = JNI_TRUE;
         } else if (JLI_StrCmp(arg, "-X") == 0) {
             printXUsage = JNI_TRUE;
             return JNI_TRUE;
+        } else if (JLI_StrCmp(arg, "--help-extra") == 0) {
+            printXUsage = JNI_TRUE;
+            printTo = USE_STDOUT;
+            return JNI_TRUE;
 /*
  * The following case checks for -XshowSettings OR -XshowSetting:SUBOPT.
  * In the latter case, any SUBOPT value not recognized will default to "all"
@@ -1330,6 +1350,9 @@
         } else if (JLI_StrCmp(arg, "-fullversion") == 0) {
             JLI_ReportMessage("%s full version \"%s\"", _launcher_name, GetFullVersion());
             return JNI_FALSE;
+        } else if (JLI_StrCmp(arg, "--full-version") == 0) {
+            JLI_ShowMessage("%s %s", _launcher_name, GetFullVersion());
+            return JNI_FALSE;
         } else if (JLI_StrCmp(arg, "-verbosegc") == 0) {
             AddOption("-verbose:gc", NULL);
         } else if (JLI_StrCmp(arg, "-t") == 0) {
@@ -1752,11 +1775,11 @@
     NULL_CHECK(print = (*env)->GetStaticMethodID(env,
                                                  ver,
                                                  (extraLF == JNI_TRUE) ? "println" : "print",
-                                                 "()V"
+                                                 "(Z)V"
                                                  )
               );
 
-    (*env)->CallStaticVoidMethod(env, ver, print);
+    (*env)->CallStaticVoidMethod(env, ver, print, printTo);
 }
 
 /*
@@ -1794,7 +1817,7 @@
             "listModules", "(ZLjava/lang/String;)V"));
     NULL_CHECK(joptString = (*env)->NewStringUTF(env, optString));
     (*env)->CallStaticVoidMethod(env, cls, listModulesID,
-                                 USE_STDERR,
+                                 USE_STDOUT,
                                  joptString);
 }
 
@@ -1812,7 +1835,7 @@
   if (doXUsage) {
     NULL_CHECK(printXUsageMessage = (*env)->GetStaticMethodID(env, cls,
                                         "printXUsageMessage", "(Z)V"));
-    (*env)->CallStaticVoidMethod(env, cls, printXUsageMessage, USE_STDERR);
+    (*env)->CallStaticVoidMethod(env, cls, printXUsageMessage, printTo);
   } else {
     NULL_CHECK(initHelp = (*env)->GetStaticMethodID(env, cls,
                                         "initHelpMessage", "(Ljava/lang/String;)V"));
@@ -1853,7 +1876,7 @@
     }
 
     /* Complete the usage message and print to stderr*/
-    (*env)->CallStaticVoidMethod(env, cls, printHelp, USE_STDERR);
+    (*env)->CallStaticVoidMethod(env, cls, printHelp, printTo);
   }
   return;
 }
@@ -2255,3 +2278,16 @@
     fprintf(stderr, "\n");
     va_end(vl);
 }
+
+/*
+ * A utility procedure to always print to stdout
+ */
+void
+JLI_ShowMessage(const char* fmt, ...)
+{
+    va_list vl;
+    va_start(vl, fmt);
+    vfprintf(stdout, fmt, vl);
+    fprintf(stdout, "\n");
+    va_end(vl);
+}
diff --git a/jdk/src/java.base/share/native/libjli/java.h b/jdk/src/java.base/share/native/libjli/java.h
index 189bffc..81f86a0 100644
--- a/jdk/src/java.base/share/native/libjli/java.h
+++ b/jdk/src/java.base/share/native/libjli/java.h
@@ -140,6 +140,9 @@
 /* Reports an error message only to stderr. */
 void JLI_ReportMessage(const char * message, ...);
 
+/* Reports a message only to stdout. */
+void JLI_ShowMessage(const char * message, ...);
+
 /*
  * Reports an exception which terminates the vm to stderr or a window
  * as appropriate.
diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index 85bbd53..01213c0 100644
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
 import java.net.URL;
 import java.security.GeneralSecurityException;
 import java.util.Base64;
+import java.util.Objects;
 
 import sun.net.www.HeaderParser;
 import sun.net.www.protocol.http.AuthenticationInfo;
@@ -116,11 +117,13 @@
      * If this notation is not used, then the domain will be taken
      * from a system property: "http.auth.ntlm.domain".
      */
-    public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
+    public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw,
+                              String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
                 AuthScheme.NTLM,
                 url,
-                "");
+                "",
+                Objects.requireNonNull(authenticatorKey));
         init (pw);
     }
 
@@ -157,12 +160,14 @@
     * Constructor used for proxy entries
     */
     public NTLMAuthentication(boolean isProxy, String host, int port,
-                                PasswordAuthentication pw) {
+                              PasswordAuthentication pw,
+                              String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
                 AuthScheme.NTLM,
                 host,
                 port,
-                "");
+                "",
+                Objects.requireNonNull(authenticatorKey));
         init (pw);
     }
 
@@ -242,4 +247,3 @@
         return result;
     }
 }
-
diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index 50e0568..212e03e 100644
--- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 import java.net.PasswordAuthentication;
 import java.net.UnknownHostException;
 import java.net.URL;
+import java.util.Objects;
 import sun.net.www.HeaderParser;
 import sun.net.www.protocol.http.AuthenticationInfo;
 import sun.net.www.protocol.http.AuthScheme;
@@ -88,11 +89,13 @@
      * If this notation is not used, then the domain will be taken
      * from a system property: "http.auth.ntlm.domain".
      */
-    public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
+    public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw,
+                              String authenticatorKey) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
               AuthScheme.NTLM,
               url,
-              "");
+              "",
+              Objects.requireNonNull(authenticatorKey));
         init (pw);
     }
 
@@ -122,12 +125,14 @@
     * Constructor used for proxy entries
     */
     public NTLMAuthentication(boolean isProxy, String host, int port,
-                                PasswordAuthentication pw) {
+                              PasswordAuthentication pw,
+                              String authenticatorKey) {
         super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
               AuthScheme.NTLM,
               host,
               port,
-              "");
+              "",
+              Objects.requireNonNull(authenticatorKey));
         init (pw);
     }
 
diff --git a/jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
index 71e999f..2f4fd0e 100644
--- a/jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
+++ b/jdk/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java
@@ -52,6 +52,7 @@
 import java.util.spi.CalendarNameProvider;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleNameProvider;
+import sun.text.spi.JavaTimeDateTimePatternProvider;
 import sun.util.spi.CalendarProvider;
 
 /**
@@ -525,6 +526,167 @@
         };
     }
 
+    public static JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
+        return new JavaTimeDateTimePatternProvider() {
+            @Override
+            public Locale[] getAvailableLocales() {
+                return getSupportedCalendarLocales();
+            }
+
+            @Override
+            public boolean isSupportedLocale(Locale locale) {
+                return isSupportedCalendarLocale(locale);
+            }
+
+            @Override
+            public String getJavaTimeDateTimePattern(int timeStyle, int dateStyle, String calType, Locale locale) {
+                AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
+                String pattern = new StringBuilder(patterns.get(dateStyle / 2))
+                        .append(" ")
+                        .append(patterns.get(timeStyle / 2 + 2))
+                        .toString();
+                return toJavaTimeDateTimePattern(calType, pattern);
+
+            }
+
+            private AtomicReferenceArray<String> getDateTimePatterns(Locale locale) {
+                AtomicReferenceArray<String> patterns;
+                SoftReference<AtomicReferenceArray<String>> ref = dateFormatCache.get(locale);
+
+                if (ref == null || (patterns = ref.get()) == null) {
+                    String langtag = removeExtensions(locale).toLanguageTag();
+                    patterns = new AtomicReferenceArray<>(4);
+                    patterns.compareAndSet(0, null, convertDateTimePattern(
+                            getDateTimePattern(DateFormat.LONG, -1, langtag)));
+                    patterns.compareAndSet(1, null, convertDateTimePattern(
+                            getDateTimePattern(DateFormat.SHORT, -1, langtag)));
+                    patterns.compareAndSet(2, null, convertDateTimePattern(
+                            getDateTimePattern(-1, DateFormat.LONG, langtag)));
+                    patterns.compareAndSet(3, null, convertDateTimePattern(
+                            getDateTimePattern(-1, DateFormat.SHORT, langtag)));
+                    ref = new SoftReference<>(patterns);
+                    dateFormatCache.put(locale, ref);
+                }
+                return patterns;
+            }
+            /**
+             * This method will convert JRE Date/time Pattern String to JSR310
+             * type Date/Time Pattern
+             */
+            private String toJavaTimeDateTimePattern(String calendarType, String jrePattern) {
+                int length = jrePattern.length();
+                StringBuilder sb = new StringBuilder(length);
+                boolean inQuote = false;
+                int count = 0;
+                char lastLetter = 0;
+                for (int i = 0; i < length; i++) {
+                    char c = jrePattern.charAt(i);
+                    if (c == '\'') {
+                        // '' is treated as a single quote regardless of being
+                        // in a quoted section.
+                        if ((i + 1) < length) {
+                            char nextc = jrePattern.charAt(i + 1);
+                            if (nextc == '\'') {
+                                i++;
+                                if (count != 0) {
+                                    convert(calendarType, lastLetter, count, sb);
+                                    lastLetter = 0;
+                                    count = 0;
+                                }
+                                sb.append("''");
+                                continue;
+                            }
+                        }
+                        if (!inQuote) {
+                            if (count != 0) {
+                                convert(calendarType, lastLetter, count, sb);
+                                lastLetter = 0;
+                                count = 0;
+                            }
+                            inQuote = true;
+                        } else {
+                            inQuote = false;
+                        }
+                        sb.append(c);
+                        continue;
+                    }
+                    if (inQuote) {
+                        sb.append(c);
+                        continue;
+                    }
+                    if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
+                        if (count != 0) {
+                            convert(calendarType, lastLetter, count, sb);
+                            lastLetter = 0;
+                            count = 0;
+                        }
+                        sb.append(c);
+                        continue;
+                    }
+                    if (lastLetter == 0 || lastLetter == c) {
+                        lastLetter = c;
+                        count++;
+                        continue;
+                    }
+                    convert(calendarType, lastLetter, count, sb);
+                    lastLetter = c;
+                    count = 1;
+                }
+                if (inQuote) {
+                    // should not come here.
+                    // returning null so that FALLBACK provider will kick in.
+                    return null;
+                }
+                if (count != 0) {
+                    convert(calendarType, lastLetter, count, sb);
+                }
+                return sb.toString();
+            }
+
+            private void convert(String calendarType, char letter, int count, StringBuilder sb) {
+                switch (letter) {
+                    case 'G':
+                        if (calendarType.equals("japanese")) {
+                            if (count >= 4) {
+                                count = 1;
+                            } else {
+                                count = 5;
+                            }
+                        } else if (!calendarType.equals("iso8601")) {
+                            // Adjust the number of 'G's
+                            // Gregorian calendar is iso8601 for java.time
+                            if (count >= 4) {
+                                // JRE full -> JavaTime full
+                                count = 4;
+                            } else {
+                                // JRE short -> JavaTime short
+                                count = 1;
+                            }
+                        }
+                        break;
+                    case 'y':
+                        if (calendarType.equals("japanese") && count >= 4) {
+                            // JRE specific "gan-nen" support
+                            count = 1;
+                        }
+                        break;
+                    default:
+                        // JSR 310 and CLDR define 5-letter patterns for narrow text.
+                        if (count > 4) {
+                            count = 4;
+                        }
+                        break;
+                }
+                appendN(letter, count, sb);
+            }
+
+            private void appendN(char c, int n, StringBuilder sb) {
+                for (int i = 0; i < n; i++) {
+                    sb.append(c);
+                }
+            }
+        };
+    }
 
     private static String convertDateTimePattern(String winPattern) {
         String ret = winPattern.replaceAll("dddd", "EEEE");
diff --git a/jdk/src/java.compact1/share/classes/module-info.java b/jdk/src/java.compact1/share/classes/module-info.java
index 112c71b..72d4357 100644
--- a/jdk/src/java.compact1/share/classes/module-info.java
+++ b/jdk/src/java.compact1/share/classes/module-info.java
@@ -27,7 +27,7 @@
  * Aggregates {@code java.base}, {@code java.logging}, and {@code java.scripting}.
  */
 module java.compact1 {
-    requires public java.logging;
-    requires public java.scripting;
+    requires transitive java.logging;
+    requires transitive java.scripting;
 }
 
diff --git a/jdk/src/java.compact2/share/classes/module-info.java b/jdk/src/java.compact2/share/classes/module-info.java
index b199024..0666be8 100644
--- a/jdk/src/java.compact2/share/classes/module-info.java
+++ b/jdk/src/java.compact2/share/classes/module-info.java
@@ -27,9 +27,9 @@
  * Supplements {@code java.compact1} with JDBC, JAXP, and RMI.
  */
 module java.compact2 {
-    requires public java.compact1;
-    requires public java.rmi;
-    requires public java.sql;
-    requires public java.xml;
+    requires transitive java.compact1;
+    requires transitive java.rmi;
+    requires transitive java.sql;
+    requires transitive java.xml;
 }
 
diff --git a/jdk/src/java.compact3/share/classes/module-info.java b/jdk/src/java.compact3/share/classes/module-info.java
index 05f33c0..9783a40 100644
--- a/jdk/src/java.compact3/share/classes/module-info.java
+++ b/jdk/src/java.compact3/share/classes/module-info.java
@@ -28,15 +28,15 @@
  * Instrumentation, Preferences, Security, and XML cryptography APIs.
  */
 module java.compact3 {
-    requires public java.compact2;
-    requires public java.compiler;
-    requires public java.instrument;
-    requires public java.management;
-    requires public java.naming;
-    requires public java.prefs;
-    requires public java.security.jgss;
-    requires public java.security.sasl;
-    requires public java.sql.rowset;
-    requires public java.xml.crypto;
+    requires transitive java.compact2;
+    requires transitive java.compiler;
+    requires transitive java.instrument;
+    requires transitive java.management;
+    requires transitive java.naming;
+    requires transitive java.prefs;
+    requires transitive java.security.jgss;
+    requires transitive java.security.sasl;
+    requires transitive java.sql.rowset;
+    requires transitive java.xml.crypto;
 }
 
diff --git a/jdk/src/java.desktop/share/classes/module-info.java b/jdk/src/java.desktop/share/classes/module-info.java
index 0a49c8b..bb7abf1 100644
--- a/jdk/src/java.desktop/share/classes/module-info.java
+++ b/jdk/src/java.desktop/share/classes/module-info.java
@@ -28,8 +28,8 @@
  * accessibility, audio, imaging, printing, and JavaBeans.
  */
 module java.desktop {
-    requires public java.datatransfer;
-    requires public java.xml;
+    requires transitive java.datatransfer;
+    requires transitive java.xml;
     requires java.prefs;
 
     exports java.applet;
@@ -91,6 +91,11 @@
     exports com.sun.awt to
         jdk.desktop;
 
+    opens javax.swing.plaf.basic to
+        jdk.jconsole;
+    opens com.sun.java.swing.plaf.windows to
+        jdk.jconsole;
+
     uses java.awt.im.spi.InputMethodDescriptor;
     uses javax.accessibility.AccessibilityProvider;
     uses javax.imageio.spi.ImageInputStreamSpi;
@@ -113,31 +118,44 @@
     provides java.net.ContentHandlerFactory with sun.awt.www.content.MultimediaContentHandlers;
     provides javax.print.PrintServiceLookup with sun.print.PrintServiceLookupProvider;
     provides javax.print.StreamPrintServiceFactory with sun.print.PSStreamPrinterFactory;
-    provides javax.sound.midi.spi.MidiDeviceProvider with com.sun.media.sound.MidiInDeviceProvider;
-    provides javax.sound.midi.spi.MidiDeviceProvider with com.sun.media.sound.MidiOutDeviceProvider;
-    provides javax.sound.midi.spi.MidiDeviceProvider with com.sun.media.sound.RealTimeSequencerProvider;
-    provides javax.sound.midi.spi.MidiDeviceProvider with com.sun.media.sound.SoftProvider;
+
+    provides javax.sound.midi.spi.MidiDeviceProvider with
+        com.sun.media.sound.MidiInDeviceProvider,
+        com.sun.media.sound.MidiOutDeviceProvider,
+        com.sun.media.sound.RealTimeSequencerProvider,
+        com.sun.media.sound.SoftProvider;
+
     provides javax.sound.midi.spi.MidiFileReader with com.sun.media.sound.StandardMidiFileReader;
     provides javax.sound.midi.spi.MidiFileWriter with com.sun.media.sound.StandardMidiFileWriter;
-    provides javax.sound.midi.spi.SoundbankReader with com.sun.media.sound.AudioFileSoundbankReader;
-    provides javax.sound.midi.spi.SoundbankReader with com.sun.media.sound.DLSSoundbankReader;
-    provides javax.sound.midi.spi.SoundbankReader with com.sun.media.sound.JARSoundbankReader;
-    provides javax.sound.midi.spi.SoundbankReader with com.sun.media.sound.SF2SoundbankReader;
-    provides javax.sound.sampled.spi.AudioFileReader with com.sun.media.sound.AiffFileReader;
-    provides javax.sound.sampled.spi.AudioFileReader with com.sun.media.sound.AuFileReader;
-    provides javax.sound.sampled.spi.AudioFileReader with com.sun.media.sound.SoftMidiAudioFileReader;
-    provides javax.sound.sampled.spi.AudioFileReader with com.sun.media.sound.WaveFileReader;
-    provides javax.sound.sampled.spi.AudioFileReader with com.sun.media.sound.WaveFloatFileReader;
-    provides javax.sound.sampled.spi.AudioFileReader with com.sun.media.sound.WaveExtensibleFileReader;
-    provides javax.sound.sampled.spi.AudioFileWriter with com.sun.media.sound.AiffFileWriter;
-    provides javax.sound.sampled.spi.AudioFileWriter with com.sun.media.sound.AuFileWriter;
-    provides javax.sound.sampled.spi.AudioFileWriter with com.sun.media.sound.WaveFileWriter;
-    provides javax.sound.sampled.spi.AudioFileWriter with com.sun.media.sound.WaveFloatFileWriter;
-    provides javax.sound.sampled.spi.FormatConversionProvider with com.sun.media.sound.AlawCodec;
-    provides javax.sound.sampled.spi.FormatConversionProvider with com.sun.media.sound.AudioFloatFormatConverter;
-    provides javax.sound.sampled.spi.FormatConversionProvider with com.sun.media.sound.PCMtoPCMCodec;
-    provides javax.sound.sampled.spi.FormatConversionProvider with com.sun.media.sound.UlawCodec;
-    provides javax.sound.sampled.spi.MixerProvider with com.sun.media.sound.DirectAudioDeviceProvider;
-    provides javax.sound.sampled.spi.MixerProvider with com.sun.media.sound.PortMixerProvider;
+
+    provides javax.sound.midi.spi.SoundbankReader with
+         com.sun.media.sound.AudioFileSoundbankReader,
+         com.sun.media.sound.DLSSoundbankReader,
+         com.sun.media.sound.JARSoundbankReader,
+         com.sun.media.sound.SF2SoundbankReader;
+
+    provides javax.sound.sampled.spi.AudioFileReader with
+        com.sun.media.sound.AiffFileReader,
+        com.sun.media.sound.AuFileReader,
+        com.sun.media.sound.SoftMidiAudioFileReader,
+        com.sun.media.sound.WaveFileReader,
+        com.sun.media.sound.WaveFloatFileReader,
+        com.sun.media.sound.WaveExtensibleFileReader;
+
+    provides javax.sound.sampled.spi.AudioFileWriter with
+        com.sun.media.sound.AiffFileWriter,
+        com.sun.media.sound.AuFileWriter,
+        com.sun.media.sound.WaveFileWriter,
+        com.sun.media.sound.WaveFloatFileWriter;
+
+    provides javax.sound.sampled.spi.FormatConversionProvider with
+        com.sun.media.sound.AlawCodec,
+        com.sun.media.sound.AudioFloatFormatConverter,
+        com.sun.media.sound.PCMtoPCMCodec,
+        com.sun.media.sound.UlawCodec;
+
+    provides javax.sound.sampled.spi.MixerProvider with
+        com.sun.media.sound.DirectAudioDeviceProvider,
+        com.sun.media.sound.PortMixerProvider;
 }
 
diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java b/jdk/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java
index eef1b6e..97986c2 100644
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java
+++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java
@@ -27,6 +27,9 @@
 
 import java.lang.reflect.Module;
 import java.security.ProtectionDomain;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.jar.JarFile;
 
 /*
@@ -660,19 +663,62 @@
     setNativeMethodPrefix(ClassFileTransformer transformer, String prefix);
 
     /**
-     * Updates a module to read another module.
+     * Redefine a module to expand the set of modules that it reads, the set of
+     * packages that it exports or opens, or the services that it uses or
+     * provides. This method facilitates the instrumentation of code in named
+     * modules where that instrumentation requires changes to the set of modules
+     * that are read, the packages that are exported or open, or the services
+     * that are used or provided.
      *
-     * Agents that instrument code in named modules may need to arrange for the
-     * modules to read other modules. This method is equivalent to code in {@code
-     * module} calling {@link Module#addReads(Module) addReads} to read {@code
-     * other}.
+     * <p> This method cannot reduce the set of modules that a module reads, nor
+     * reduce the set of packages that it exports or opens, nor reduce the set
+     * of services that it uses or provides. This method is a no-op when invoked
+     * to redefine an unnamed module. </p>
      *
-     * @param module the module to update
-     * @param other the module to read
-     * @throws NullPointerException if either module is {@code null}
+     * <p> When expanding the services that a module uses or provides then the
+     * onus is on the agent to ensure that the service type will be accessible at
+     * each instrumentation site where the service type is used. This method
+     * does not check if the service type is a member of the module or in a
+     * package exported to the module by another module that it reads. </p>
      *
+     * <p> The {@code extraExports} parameter is the map of additional packages
+     * to export. The {@code extraOpens} parameter is the map of additional
+     * packages to open. In both cases, the map key is the fully-qualified name
+     * of the package as defined in section 6.5.3 of
+     * <cite>The Java&trade; Language Specification </cite>, for example, {@code
+     * "java.lang"}. The map value is the non-empty set of modules that the
+     * package should be exported or opened to. </p>
+     *
+     * <p> The {@code extraProvides} parameter is the additional service providers
+     * for the module to provide. The map key is the service type. The map value
+     * is the non-empty list of implementation types, each of which is a member
+     * of the module and an implementation of the service. </p>
+     *
+     * <p> This method is safe for concurrent use and so allows multiple agents
+     * to instrument and update the same module at around the same time. </p>
+     *
+     * @param module the module to redefine
+     * @param extraReads the possibly-empty set of additional modules to read
+     * @param extraExports the possibly-empty map of additional packages to export
+     * @param extraOpens the possibly-empty map of additional packages to open
+     * @param extraUses the possibly-empty set of additional services to use
+     * @param extraProvides the possibly-empty map of additional services to provide
+     *
+     * @throws IllegalArgumentException
+     *         If {@code extraExports} or {@code extraOpens} contains a key
+     *         that is not a package in the module; if {@code extraExports} or
+     *         {@code extraOpens} maps a key to an empty set; if a value in the
+     *         {@code extraProvides} map contains a service provider type that
+     *         is not a member of the module or an implementation of the service;
+     *         or {@code extraProvides} maps a key to an empty list
+     * @throws NullPointerException if any of the arguments are {@code null} or
+     *         any of the Sets or Maps contains a {@code null} key or value
      * @since 9
-     * @see Module#canRead(Module)
      */
-    void addModuleReads(Module module, Module other);
+    void redefineModule(Module module,
+                        Set<Module> extraReads,
+                        Map<String, Set<Module>> extraExports,
+                        Map<String, Set<Module>> extraOpens,
+                        Set<Class<?>> extraUses,
+                        Map<Class<?>, List<Class<?>>> extraProvides);
 }
diff --git a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
index c1f6c85..e7f8d8f 100644
--- a/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
+++ b/jdk/src/java.instrument/share/classes/java/lang/instrument/package.html
@@ -277,15 +277,6 @@
 
 <h3>Instrumenting code in modules</h3>
 
-Agents that instrument code in named modules may need to arrange for the
-modules to read other modules. If code is instrumented to invoke a method
-in a support class in another module, then the module of the instrumented
-code should read the module of the supporting class. Furthermore, the
-supporting class will only be accessible to the instrumented code if
-it is <code>public</code> and in a package that is exported by its module.
-Agents can use {@link Instrumentation#addModuleReads addModuleReads} to update
-a module to read another.
-<p>
 As an aid to agents that deploy supporting classes on the search path of the
 bootstrap class loader, or the search path of the class loader that loads
 the main agent class, the Java virtual machine arranges for the module of
diff --git a/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java b/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
index 80c2e74..b2c2a24 100644
--- a/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
+++ b/jdk/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java
@@ -29,18 +29,23 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Module;
 import java.lang.reflect.AccessibleObject;
-
 import java.lang.instrument.ClassFileTransformer;
 import java.lang.instrument.ClassDefinition;
 import java.lang.instrument.Instrumentation;
-
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
-
-import java.util.Objects;
+import java.util.Collections;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.jar.JarFile;
 
+import jdk.internal.module.Modules;
+
 /*
  * Copyright 2003 Wily Technology, Inc.
  */
@@ -228,10 +233,100 @@
     }
 
     @Override
-    public void addModuleReads(Module module, Module other) {
-        Objects.requireNonNull(module);
-        Objects.requireNonNull(other);
-        jdk.internal.module.Modules.addReads(module, other);
+    public void redefineModule(Module module,
+                               Set<Module> extraReads,
+                               Map<String, Set<Module>> extraExports,
+                               Map<String, Set<Module>> extraOpens,
+                               Set<Class<?>> extraUses,
+                               Map<Class<?>, List<Class<?>>> extraProvides)
+    {
+        if (!module.isNamed())
+            return;
+
+        // copy and check reads
+        extraReads = new HashSet<>(extraReads);
+        if (extraReads.contains(null))
+            throw new NullPointerException("'extraReads' contains null");
+
+        // copy and check exports and opens
+        extraExports = cloneAndCheckMap(module, extraExports);
+        extraOpens = cloneAndCheckMap(module, extraOpens);
+
+        // copy and check uses
+        extraUses = new HashSet<>(extraUses);
+        if (extraUses.contains(null))
+            throw new NullPointerException("'extraUses' contains null");
+
+        // copy and check provides
+        Map<Class<?>, List<Class<?>>> tmpProvides = new HashMap<>();
+        for (Map.Entry<Class<?>, List<Class<?>>> e : extraProvides.entrySet()) {
+            Class<?> service = e.getKey();
+            if (service == null)
+                throw new NullPointerException("'extraProvides' contains null");
+            List<Class<?>> providers = new ArrayList<>(e.getValue());
+            if (providers.isEmpty())
+                throw new IllegalArgumentException("list of providers is empty");
+            providers.forEach(p -> {
+                if (p.getModule() != module)
+                    throw new IllegalArgumentException(p + " not in " + module);
+                if (!service.isAssignableFrom(p))
+                    throw new IllegalArgumentException(p + " is not a " + service);
+            });
+            tmpProvides.put(service, providers);
+        }
+        extraProvides = tmpProvides;
+
+
+        // update reads
+        extraReads.forEach(m -> Modules.addReads(module, m));
+
+        // update exports
+        for (Map.Entry<String, Set<Module>> e : extraExports.entrySet()) {
+            String pkg = e.getKey();
+            Set<Module> targets = e.getValue();
+            targets.forEach(m -> Modules.addExports(module, pkg, m));
+        }
+
+        // update opens
+        for (Map.Entry<String, Set<Module>> e : extraOpens.entrySet()) {
+            String pkg = e.getKey();
+            Set<Module> targets = e.getValue();
+            targets.forEach(m -> Modules.addOpens(module, pkg, m));
+        }
+
+        // update uses
+        extraUses.forEach(service -> Modules.addUses(module, service));
+
+        // update provides
+        for (Map.Entry<Class<?>, List<Class<?>>> e : extraProvides.entrySet()) {
+            Class<?> service = e.getKey();
+            List<Class<?>> providers = e.getValue();
+            providers.forEach(p -> Modules.addProvides(module, service, p));
+        }
+    }
+
+    private Map<String, Set<Module>>
+        cloneAndCheckMap(Module module, Map<String, Set<Module>> map)
+    {
+        if (map.isEmpty())
+            return Collections.emptyMap();
+
+        Map<String, Set<Module>> result = new HashMap<>();
+        Set<String> packages = Set.of(module.getPackages());
+        for (Map.Entry<String, Set<Module>> e : map.entrySet()) {
+            String pkg = e.getKey();
+            if (pkg == null)
+                throw new NullPointerException("package cannot be null");
+            if (!packages.contains(pkg))
+                throw new IllegalArgumentException(pkg + " not in module");
+            Set<Module> targets = new HashSet<>(e.getValue());
+            if (targets.isEmpty())
+                throw new IllegalArgumentException("set of targets is empty");
+            if (targets.contains(null))
+                throw new NullPointerException("set of targets cannot include null");
+            result.put(pkg, targets);
+        }
+        return result;
     }
 
 
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Level.java b/jdk/src/java.logging/share/classes/java/util/logging/Level.java
index f7f7a43..98597d3 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/Level.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Level.java
@@ -40,6 +40,8 @@
 import java.util.ResourceBundle;
 import java.util.function.Function;
 import jdk.internal.loader.ClassLoaderValue;
+import jdk.internal.misc.JavaUtilResourceBundleAccess;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  * The Level class defines a set of standard logging levels that
@@ -74,7 +76,11 @@
  */
 
 public class Level implements java.io.Serializable {
-    private static final String defaultBundle = "sun.util.logging.resources.logging";
+    private static final String defaultBundle =
+        "sun.util.logging.resources.logging";
+
+    private static final JavaUtilResourceBundleAccess RB_ACCESS =
+        SharedSecrets.getJavaUtilResourceBundleAccess();
 
     /**
      * @serial  The non-localized name of the level.
@@ -280,7 +286,7 @@
         // or its defining class loader, if it's unnamed module,
         // of this Level instance that can be a custom Level subclass;
         Module module = this.getClass().getModule();
-        ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName,
+        ResourceBundle rb = RB_ACCESS.getBundle(resourceBundleName,
                 newLocale, module);
 
         final String localizedName = rb.getString(name);
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java
index b196283..dce8c4c 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java
@@ -38,6 +38,9 @@
 import java.util.ResourceBundle;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.function.Supplier;
+
+import jdk.internal.misc.JavaUtilResourceBundleAccess;
+import jdk.internal.misc.SharedSecrets;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 import static jdk.internal.logger.DefaultLoggerFinder.isSystem;
@@ -256,8 +259,8 @@
     private static final LoggerBundle NO_RESOURCE_BUNDLE =
             new LoggerBundle(null, null);
 
-    private static final RuntimePermission GET_CLASS_LOADER_PERMISSION =
-            new RuntimePermission("getClassLoader");
+    private static final JavaUtilResourceBundleAccess RB_ACCESS =
+            SharedSecrets.getJavaUtilResourceBundleAccess();
 
     // A value class that holds the logger configuration data.
     // This configuration can be shared between an application logger
@@ -2180,9 +2183,7 @@
         if (!useCallersModule || callerModule == null || !callerModule.isNamed()) {
             try {
                 Module mod = cl.getUnnamedModule();
-                PrivilegedAction<ResourceBundle> pa = () ->
-                    ResourceBundle.getBundle(name, currentLocale, mod);
-                catalog = AccessController.doPrivileged(pa, null, GET_CLASS_LOADER_PERMISSION);
+                catalog = RB_ACCESS.getBundle(name, currentLocale, mod);
                 catalogName = name;
                 catalogLocale = currentLocale;
                 return catalog;
@@ -2226,9 +2227,7 @@
             // Try with the caller's module
             try {
                 // Use the caller's module
-                PrivilegedAction<ResourceBundle> pa = () ->
-                    ResourceBundle.getBundle(name, currentLocale, callerModule);
-                catalog = AccessController.doPrivileged(pa, null, GET_CLASS_LOADER_PERMISSION);
+                catalog = RB_ACCESS.getBundle(name, currentLocale, callerModule);
                 catalogName = name;
                 catalogLocale = currentLocale;
                 return catalog;
diff --git a/jdk/src/java.management/share/classes/module-info.java b/jdk/src/java.management/share/classes/module-info.java
index 54ccb16..705e3ef 100644
--- a/jdk/src/java.management/share/classes/module-info.java
+++ b/jdk/src/java.management/share/classes/module-info.java
@@ -30,7 +30,7 @@
  * JVM and other components in the Java runtime.
  */
 module java.management {
-    requires public java.rmi;
+    requires transitive java.rmi;
     requires java.logging;
     requires java.naming;
 
diff --git a/jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java b/jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java
index 2de0e00..c53f4e2 100644
--- a/jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java
+++ b/jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java
@@ -625,26 +625,6 @@
                 // that has no from method to be embeded in another class.
             }
 
-            // check if a static "toCompositeData" method exists
-            try {
-                toMethod = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
-                    public Method run() throws NoSuchMethodException {
-                        Method m = javaClass.getDeclaredMethod("toCompositeData", javaClass);
-                        if (m != null
-                                && CompositeData.class.isAssignableFrom(m.getReturnType())
-                                && Modifier.isStatic(m.getModifiers())) {
-                            m.setAccessible(true);
-                            return m;
-                        } else {
-                            return null;
-                        }
-                    }
-                });
-            } catch (PrivilegedActionException e) {
-                // ignore NoSuchMethodException since we allow classes
-                // that has no from method to be embeded in another class.
-            }
-
             if (COMPOSITE_DATA_CLASS.isAssignableFrom(c)) {
                 // c implements CompositeData - set openType to null
                 // defer generating the CompositeType
diff --git a/jdk/src/java.se.ee/share/classes/module-info.java b/jdk/src/java.se.ee/share/classes/module-info.java
index d611f5e..6e2bc05 100644
--- a/jdk/src/java.se.ee/share/classes/module-info.java
+++ b/jdk/src/java.se.ee/share/classes/module-info.java
@@ -29,16 +29,17 @@
  * This module requires {@code java.se} and supplements it with modules
  * that define CORBA and Java EE APIs. These modules are upgradeable.
  */
+@SuppressWarnings("deprecation")
 module java.se.ee {
 
-    requires public java.se;
+    requires transitive java.se;
 
     // Upgradeable modules for Java EE technologies
-    requires public java.activation;
-    requires public java.annotations.common;
-    requires public java.corba;
-    requires public java.transaction;
-    requires public java.xml.bind;
-    requires public java.xml.ws;
+    requires transitive java.activation;
+    requires transitive java.annotations.common;
+    requires transitive java.corba;
+    requires transitive java.transaction;
+    requires transitive java.xml.bind;
+    requires transitive java.xml.ws;
 
 }
diff --git a/jdk/src/java.se/share/classes/module-info.java b/jdk/src/java.se/share/classes/module-info.java
index 26aeb03..3894c4f 100644
--- a/jdk/src/java.se/share/classes/module-info.java
+++ b/jdk/src/java.se/share/classes/module-info.java
@@ -31,8 +31,8 @@
  * required by {@code java.se.ee}.
  */
 module java.se {
-    requires public java.compact3;
-    requires public java.datatransfer;
-    requires public java.desktop;
-    requires public java.httpclient;
+    requires transitive java.compact3;
+    requires transitive java.datatransfer;
+    requires transitive java.desktop;
+    requires transitive java.httpclient;
 }
diff --git a/jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java b/jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java
index db03ab5..43003bf 100644
--- a/jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java
+++ b/jdk/src/java.security.jgss/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,6 +63,7 @@
             answered = true;
             PasswordAuthentication passAuth =
                     Authenticator.requestPasswordAuthentication(
+                    hci.authenticator,
                     hci.host, hci.addr, hci.port, hci.protocol,
                     hci.prompt, hci.scheme, hci.url, hci.authType);
             /**
diff --git a/jdk/src/java.sql.rowset/share/classes/module-info.java b/jdk/src/java.sql.rowset/share/classes/module-info.java
index 8d24418..b2c27bc 100644
--- a/jdk/src/java.sql.rowset/share/classes/module-info.java
+++ b/jdk/src/java.sql.rowset/share/classes/module-info.java
@@ -27,9 +27,9 @@
  * Defines the JDBC RowSet API.
  */
 module java.sql.rowset {
-    requires public java.logging;
-    requires public java.naming;
-    requires public java.sql;
+    requires transitive java.logging;
+    requires transitive java.naming;
+    requires transitive java.sql;
 
     exports javax.sql.rowset;
     exports javax.sql.rowset.serial;
diff --git a/jdk/src/java.sql/share/classes/module-info.java b/jdk/src/java.sql/share/classes/module-info.java
index 70764a0..14491db 100644
--- a/jdk/src/java.sql/share/classes/module-info.java
+++ b/jdk/src/java.sql/share/classes/module-info.java
@@ -27,8 +27,8 @@
  * Defines the JDBC API.
  */
 module java.sql {
-    requires public java.logging;
-    requires public java.xml;
+    requires transitive java.logging;
+    requires transitive java.xml;
 
     exports java.sql;
     exports javax.sql;
diff --git a/jdk/src/java.transaction/share/classes/module-info.java b/jdk/src/java.transaction/share/classes/module-info.java
index 84daf74..4e24512 100644
--- a/jdk/src/java.transaction/share/classes/module-info.java
+++ b/jdk/src/java.transaction/share/classes/module-info.java
@@ -30,7 +30,7 @@
  * exceptions by the 'Java Language to IDL Mapping Specification'.
  */
 module java.transaction {
-    requires public java.rmi;
+    requires transitive java.rmi;
     exports javax.transaction;
 }
 
diff --git a/jdk/src/java.xml.crypto/share/classes/module-info.java b/jdk/src/java.xml.crypto/share/classes/module-info.java
index 62694bb..4bd55f9 100644
--- a/jdk/src/java.xml.crypto/share/classes/module-info.java
+++ b/jdk/src/java.xml.crypto/share/classes/module-info.java
@@ -27,7 +27,7 @@
  * Defines an API for XML cryptography.
  */
 module java.xml.crypto {
-    requires public java.xml;
+    requires transitive java.xml;
     requires java.logging;
 
     exports javax.xml.crypto;
diff --git a/jdk/src/jdk.accessibility/share/classes/module-info.java b/jdk/src/jdk.accessibility/share/classes/module-info.java
index e72b5b7..5f0b63f 100644
--- a/jdk/src/jdk.accessibility/share/classes/module-info.java
+++ b/jdk/src/jdk.accessibility/share/classes/module-info.java
@@ -24,7 +24,7 @@
  */
 
 module jdk.accessibility {
-    requires public java.desktop;
+    requires transitive java.desktop;
     exports com.sun.java.accessibility.util;
 }
 
diff --git a/jdk/src/jdk.attach/share/classes/module-info.java b/jdk/src/jdk.attach/share/classes/module-info.java
index a6f7a7e..6cb8c00 100644
--- a/jdk/src/jdk.attach/share/classes/module-info.java
+++ b/jdk/src/jdk.attach/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the attach API.
+ */
 module jdk.attach {
     requires jdk.jvmstat;
 
diff --git a/jdk/src/jdk.desktop/share/classes/module-info.java b/jdk/src/jdk.desktop/share/classes/module-info.java
index d02b6b4..2aac00d 100644
--- a/jdk/src/jdk.desktop/share/classes/module-info.java
+++ b/jdk/src/jdk.desktop/share/classes/module-info.java
@@ -28,7 +28,7 @@
  */
 
 module jdk.desktop {
-    requires public java.desktop;
+    requires transitive java.desktop;
 
     exports jdk.awt;
 }
diff --git a/jdk/src/jdk.internal.le/share/classes/module-info.java b/jdk/src/jdk.internal.le/share/classes/module-info.java
index d52b3b5..db859df 100644
--- a/jdk/src/jdk.internal.le/share/classes/module-info.java
+++ b/jdk/src/jdk.internal.le/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Internal API for line editing
+ */
 module jdk.internal.le {
     exports jdk.internal.jline to
         jdk.scripting.nashorn.shell,
diff --git a/jdk/src/jdk.internal.opt/share/classes/module-info.java b/jdk/src/jdk.internal.opt/share/classes/module-info.java
index dc5d39b..be862b7 100644
--- a/jdk/src/jdk.internal.opt/share/classes/module-info.java
+++ b/jdk/src/jdk.internal.opt/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Internal option processing API
+ */
 module jdk.internal.opt {
     exports jdk.internal.joptsimple to jdk.jlink, jdk.jshell;
 }
diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
index 28e0752..f9b3276 100644
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
@@ -30,6 +30,7 @@
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
 import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Version;
 import java.lang.module.ModuleFinder;
@@ -58,6 +59,7 @@
 
 import jdk.internal.misc.JavaLangModuleAccess;
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.Checks;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleInfoExtender;
 import jdk.internal.util.jar.JarIndex;
@@ -80,7 +82,7 @@
     String fname, mname, ename;
     String zname = "";
     String rootjar = null;
-    Set<String> concealedPackages = new HashSet<>();
+    Set<String> concealedPackages = new HashSet<>(); // used by Validator
 
     private static final int BASE_VERSION = 0;
 
@@ -90,6 +92,13 @@
         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) {
             this.file = file;
             String path = file.getPath();
@@ -105,6 +114,21 @@
             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);
+        }
+
         @Override
         public boolean equals(Object o) {
             if (this == o) return true;
@@ -488,7 +512,9 @@
             } else if (printModuleDescriptor) {
                 boolean found;
                 if (fname != null) {
-                    found = printModuleDescriptor(new ZipFile(fname));
+                    try (ZipFile zf = new ZipFile(fname)) {
+                        found = printModuleDescriptor(zf);
+                    }
                 } else {
                     try (FileInputStream fin = new FileInputStream(FileDescriptor.in)) {
                         found = printModuleDescriptor(fin);
@@ -748,6 +774,12 @@
         /* parse file arguments */
         int n = args.length - count;
         if (n > 0) {
+            if (printModuleDescriptor) {
+                // "--print-module-descriptor/-d" does not require file argument(s)
+                error(formatMsg("error.bad.dflag", args[count]));
+                usageError();
+                return false;
+            }
             int version = BASE_VERSION;
             int k = 0;
             String[] nameBuf = new String[n];
@@ -822,21 +854,27 @@
         return true;
     }
 
-    private static String toPackageName(ZipEntry entry) {
-        return toPackageName(entry.getName());
+    /*
+     * Add the package of the given resource name if it's a .class
+     * or a resource in a named package.
+     */
+    boolean addPackageIfNamed(String name) {
+        if (name.startsWith(VERSIONS_DIR)) {
+            throw new InternalError(name);
+        }
+
+        String pn = toPackageName(name);
+        // add if this is a class or resource in a package
+        if (Checks.isJavaIdentifier(pn)) {
+            packages.add(pn);
+            return true;
+        }
+
+        return false;
     }
 
     private static String toPackageName(String path) {
-        assert path.endsWith(".class");
-        int index;
-        if (path.startsWith(VERSIONS_DIR)) {
-            index = path.indexOf('/', VERSIONS_DIR.length());
-            if (index <= 0) {
-                return "";
-            }
-            path = path.substring(index + 1);
-        }
-        index = path.lastIndexOf('/');
+        int index = path.lastIndexOf('/');
         if (index != -1) {
             return path.substring(0, index).replace('/', '.');
         } else {
@@ -844,6 +882,48 @@
         }
     }
 
+    /*
+     * 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;
+            }
+        }
+        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.
@@ -865,28 +945,47 @@
             else
                 f = new File(dir, files[i]);
 
-            Entry entry = new Entry(version, f);
-            String entryName = entry.entryname;
-
+            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 (entries.add(entry)) {
-                    jarEntries.add(entryName);
-                    if (entry.basename.endsWith(".class"))
-                        packages.add(toPackageName(entry.basename));
-                    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 {
+                    error(formatMsg2("error.release.unexpected.versioned.entry",
+                                      entry.basename, String.valueOf(version)));
+                    ok = false;
                 }
             } else if (f.isDirectory()) {
-                if (entries.add(entry)) {
-                    if (isUpdate) {
-                        entryMap.put(entryName, entry);
+                if (isValidVersionedEntry(entry, version)) {
+                    if (entries.add(entry)) {
+                        if (isUpdate) {
+                            entryMap.put(entryName, entry);
+                        }
                     }
-                    expand(f, f.list(), isUpdate, moduleInfoPaths, version);
+                } 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(), isUpdate, moduleInfoPaths, version);
             } else {
                 error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
                 ok = false;
@@ -1047,6 +1146,7 @@
             } else if (moduleInfos != null && isModuleInfoEntry) {
                 moduleInfos.putIfAbsent(name, readModuleInfo(zis));
             } else {
+                boolean isDir = e.isDirectory();
                 if (!entryMap.containsKey(name)) { // copy the old stuff
                     // do our own compression
                     ZipEntry e2 = new ZipEntry(name);
@@ -1065,11 +1165,14 @@
                     addFile(zos, ent);
                     entryMap.remove(name);
                     entries.remove(ent);
+                    isDir = ent.isDir;
                 }
 
                 jarEntries.add(name);
-                if (name.endsWith(".class"))
-                    packages.add(toPackageName(name));
+                if (!isDir) {
+                    // add the package if it's a class or resource
+                    addPackageIfNamed(trimVersionsDir(name, BASE_VERSION));
+                }
             }
         }
 
@@ -1850,13 +1953,13 @@
 
     // Modular jar support
 
-    static <T> String toString(Set<T> set,
+    static <T> String toString(Collection<T> c,
                                CharSequence prefix,
                                CharSequence suffix ) {
-        if (set.isEmpty())
+        if (c.isEmpty())
             return "";
 
-        return set.stream().map(e -> e.toString())
+        return c.stream().map(e -> e.toString())
                            .collect(joining(", ", prefix, suffix));
     }
 
@@ -1890,7 +1993,7 @@
         return false;
     }
 
-    static <T> String toString(Set<T> set) {
+    static <T> String toString(Collection<T> set) {
         if (set.isEmpty()) { return ""; }
         return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
                   .collect(joining(" "));
@@ -1903,7 +2006,10 @@
     {
         ModuleDescriptor md = ModuleDescriptor.read(entryInputStream);
         StringBuilder sb = new StringBuilder();
-        sb.append("\n").append(md.toNameAndVersion());
+        sb.append("\n");
+        if (md.isOpen())
+            sb.append("open ");
+        sb.append(md.toNameAndVersion());
 
         md.requires().stream()
             .sorted(Comparator.comparing(Requires::name))
@@ -1921,10 +2027,17 @@
             .sorted(Comparator.comparing(Exports::source))
             .forEach(p -> sb.append("\n  exports ").append(p));
 
-        md.conceals().stream().sorted()
-            .forEach(p -> sb.append("\n  conceals ").append(p));
+        md.opens().stream()
+            .sorted(Comparator.comparing(Opens::source))
+            .forEach(p -> sb.append("\n  opens ").append(p));
 
-        md.provides().values().stream()
+        Set<String> concealed = new HashSet<>(md.packages());
+        md.exports().stream().map(Exports::source).forEach(concealed::remove);
+        md.opens().stream().map(Opens::source).forEach(concealed::remove);
+        concealed.stream().sorted()
+            .forEach(p -> sb.append("\n  contains ").append(p));
+
+        md.provides().stream()
             .sorted(Comparator.comparing(Provides::service))
             .forEach(p -> sb.append("\n  provides ").append(p.service())
                             .append(" with ")
@@ -1957,10 +2070,9 @@
     {
         ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
         Set<String> missing = md.provides()
-                                .values()
                                 .stream()
                                 .map(Provides::providers)
-                                .flatMap(Set::stream)
+                                .flatMap(List::stream)
                                 .filter(p -> !jarEntries.contains(toBinaryName(p)))
                                 .collect(Collectors.toSet());
         if (missing.size() > 0) {
@@ -1988,22 +2100,17 @@
             ModuleDescriptor vd = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
             if (!(isValidVersionedDescriptor(vd, rd)))
                 return false;
-            e.setValue(extendedInfoBytes(rd, vd, e.getValue(), concealedPackages));
+            e.setValue(extendedInfoBytes(rd, vd, e.getValue(), packages));
         }
         return true;
     }
 
-    private Set<String> findConcealedPackages(ModuleDescriptor md){
+    private Set<String> findConcealedPackages(ModuleDescriptor md) {
         Objects.requireNonNull(md);
-
-        Set<String> exports = md.exports()
-                .stream()
-                .map(Exports::source)
-                .collect(toSet());
-
-        return packages.stream()
-                .filter(p -> !exports.contains(p))
-                .collect(toSet());
+        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) {
@@ -2034,8 +2141,8 @@
             for (Requires r : vd.requires()) {
                 if (rootRequires.contains(r)) {
                     continue;
-                } else if (r.modifiers().contains(Requires.Modifier.PUBLIC)) {
-                    fatalError(getMsg("error.versioned.info.requires.public"));
+                } else if (r.modifiers().contains(Requires.Modifier.TRANSITIVE)) {
+                    fatalError(getMsg("error.versioned.info.requires.transitive"));
                     return false;
                 } else if (!isPlatformModule(r.name())) {
                     fatalError(getMsg("error.versioned.info.requires.added"));
@@ -2056,6 +2163,10 @@
             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;
@@ -2074,15 +2185,15 @@
     private byte[] extendedInfoBytes(ModuleDescriptor rootDescriptor,
                                      ModuleDescriptor md,
                                      byte[] miBytes,
-                                     Set<String> conceals)
+                                     Set<String> packages)
         throws IOException
     {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         InputStream is = new ByteArrayInputStream(miBytes);
         ModuleInfoExtender extender = ModuleInfoExtender.newExtender(is);
 
-        // Add (or replace) the ConcealedPackages attribute
-        extender.conceals(conceals);
+        // Add (or replace) the Packages attribute
+        extender.packages(packages);
 
         // --main-class
         if (ename != null)
diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
index d43231e..f1e2816 100644
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
@@ -44,6 +44,8 @@
 error.bad.eflag=\
 	'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
 	 together!
+error.bad.dflag=\
+        '-d, --print-module-descriptor' option requires no input file(s) to be specified: {0}
 error.nosuch.fileordir=\
         {0} : no such file or directory
 error.write.file=\
@@ -67,14 +69,16 @@
         in the root
 error.versioned.info.name.notequal=\
         module-info.class in a versioned directory contains incorrect name
-error.versioned.info.requires.public=\
-        module-info.class in a versioned directory contains additional "requires public"
+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=\
@@ -85,6 +89,8 @@
         release {0} not valid
 error.release.value.toosmall=\
         release {0} not valid, must be >= 9
+error.release.unexpected.versioned.entry=\
+        unexpected versioned entry {0} for release {1}
 error.validator.jarfile.exception=\
         can not validate {0}: {1}
 error.validator.jarfile.invalid=\
@@ -104,14 +110,16 @@
 error.validator.different.api=\
         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
+        entry: {0}, contains a class with internal name {1}, names do not match
 warn.validator.identical.entry=\
-        warning - entry: {0} contains a class that is identical to an entry already in the jar
+        Warning: entry {0} contains a class that\n\
+        is identical to an entry already in the jar
 warn.validator.resources.with.same.name=\
-         warning - entry: {0}, multiple resources with same name
+        Warning: entry {0}, multiple resources with same name
 warn.validator.concealed.public.class=\
-         warning - entry {0} is a public class in a concealed package, \n\
-         placing this jar on the class path will result in incompatible public interfaces
+        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
 out.added.manifest=\
         added manifest
 out.added.module-info=\
diff --git a/jdk/src/jdk.jconsole/share/classes/module-info.java b/jdk/src/jdk.jconsole/share/classes/module-info.java
index 6dfeca0..bd10ffb 100644
--- a/jdk/src/jdk.jconsole/share/classes/module-info.java
+++ b/jdk/src/jdk.jconsole/share/classes/module-info.java
@@ -24,8 +24,8 @@
  */
 
 module jdk.jconsole {
-    requires public java.desktop;
-    requires public java.management;
+    requires transitive java.desktop;
+    requires transitive java.management;
     requires java.logging;
     requires java.rmi;
     requires jdk.attach;
diff --git a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XMBeanAttributes.java b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XMBeanAttributes.java
index 0f61098..19ad4c9 100644
--- a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XMBeanAttributes.java
+++ b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XMBeanAttributes.java
@@ -40,8 +40,8 @@
 import java.util.WeakHashMap;
 
 import java.util.concurrent.ExecutionException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
 import javax.management.JMException;
 import javax.management.MBeanInfo;
 import javax.management.MBeanAttributeInfo;
@@ -81,7 +81,7 @@
 public class XMBeanAttributes extends XTable {
 
     final Logger LOGGER =
-            Logger.getLogger(XMBeanAttributes.class.getPackage().getName());
+            System.getLogger(XMBeanAttributes.class.getPackage().getName());
 
     private final static String[] columnNames =
     {Messages.NAME,
@@ -190,8 +190,8 @@
     }
 
     public void cancelCellEditing() {
-        if (LOGGER.isLoggable(Level.FINER)) {
-            LOGGER.finer("Cancel Editing Row: "+getEditingRow());
+        if (LOGGER.isLoggable(Level.TRACE)) {
+            LOGGER.log(Level.TRACE, "Cancel Editing Row: "+getEditingRow());
         }
         final TableCellEditor tableCellEditor = getCellEditor();
         if (tableCellEditor != null) {
@@ -200,8 +200,8 @@
     }
 
     public void stopCellEditing() {
-        if (LOGGER.isLoggable(Level.FINER)) {
-            LOGGER.finer("Stop Editing Row: "+getEditingRow());
+        if (LOGGER.isLoggable(Level.TRACE)) {
+            LOGGER.log(Level.TRACE, "Stop Editing Row: "+getEditingRow());
         }
         final TableCellEditor tableCellEditor = getCellEditor();
         if (tableCellEditor != null) {
@@ -211,8 +211,8 @@
 
     @Override
     public final boolean editCellAt(final int row, final int column, EventObject e) {
-        if (LOGGER.isLoggable(Level.FINER)) {
-            LOGGER.finer("editCellAt(row="+row+", col="+column+
+        if (LOGGER.isLoggable(Level.TRACE)) {
+            LOGGER.log(Level.TRACE, "editCellAt(row="+row+", col="+column+
                     ", e="+e+")");
         }
         if (JConsole.isDebug()) {
@@ -1002,8 +1002,9 @@
                 Object tableValue = model.getValueAt(e.getFirstRow(),
                                                  e.getColumn());
 
-                if (LOGGER.isLoggable(Level.FINER)) {
-                    LOGGER.finer("tableChanged: firstRow="+e.getFirstRow()+
+                if (LOGGER.isLoggable(Level.TRACE)) {
+                    LOGGER.log(Level.TRACE,
+                        "tableChanged: firstRow="+e.getFirstRow()+
                         ", lastRow="+e.getLastRow()+", column="+e.getColumn()+
                         ", value="+tableValue);
                 }
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ModuleReference.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ModuleReference.java
index 4c9d421..88c5129 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ModuleReference.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ModuleReference.java
@@ -30,17 +30,17 @@
  * A module in the target VM.
  * <p>
  * Any method on {@code ModuleReference} which directly or
- * indirectly takes {@code ModuleReference} as an parameter may throw
+ * indirectly takes {@code ModuleReference} as a parameter may throw
  * {@link com.sun.jdi.VMDisconnectedException} if the target VM is
  * disconnected and the {@link com.sun.jdi.event.VMDisconnectEvent} has been or is
  * available to be read from the {@link com.sun.jdi.event.EventQueue}.
  * <p>
  * Any method on {@code ModuleReference} which directly or
- * indirectly takes {@code ModuleReference} as an parameter may throw
+ * indirectly takes {@code ModuleReference} as a parameter may throw
  * {@link com.sun.jdi.VMOutOfMemoryException} if the target VM has run out of memory.
  * <p>
  * Any method on {@code ModuleReference} or which directly or indirectly takes
- * {@code ModuleReference} as parameter may throw
+ * {@code ModuleReference} as a parameter may throw
  * {@link com.sun.jdi.InvalidModuleException} if the mirrored module
  * has been unloaded.
  *
@@ -67,12 +67,4 @@
      * @return the {@link ClassLoaderReference} object for this module.
      */
     ClassLoaderReference classLoader();
-
-    /**
-     * Indicates if this module reads another module.
-     *
-     * @return {@code true} if this module reads {@code other},
-     *         {@code false} otherwise
-     */
-    boolean canRead(ModuleReference other);
 }
diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ModuleReferenceImpl.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ModuleReferenceImpl.java
index 6c32368..da5ffb2 100644
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ModuleReferenceImpl.java
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ModuleReferenceImpl.java
@@ -75,15 +75,4 @@
         }
         return classLoader;
     }
-
-    public synchronized boolean canRead(ModuleReference module) {
-        boolean ret;
-        try {
-            ret = JDWP.ModuleReference.CanRead.
-                process(this.vm, this, (ModuleReferenceImpl)module).canRead;
-        } catch (JDWPException ex) {
-            throw ex.toJDIException();
-        }
-        return ret;
-    }
 }
diff --git a/jdk/src/jdk.jdi/share/classes/module-info.java b/jdk/src/jdk.jdi/share/classes/module-info.java
index a7bd83d..0dd61c6 100644
--- a/jdk/src/jdk.jdi/share/classes/module-info.java
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Defines the Java Debugger Interface.
+ */
 module jdk.jdi {
     requires jdk.attach;
     requires jdk.jdwp.agent;
@@ -37,10 +40,11 @@
     uses com.sun.jdi.connect.spi.TransportService;
 
     // windows shared memory connector providers are added at build time
-    provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.ProcessAttachingConnector;
-    provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.RawCommandLineLauncher;
-    provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.SocketAttachingConnector;
-    provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.SocketListeningConnector;
-    provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.SunCommandLineLauncher;
+    provides com.sun.jdi.connect.Connector with
+        com.sun.tools.jdi.ProcessAttachingConnector,
+        com.sun.tools.jdi.RawCommandLineLauncher,
+        com.sun.tools.jdi.SocketAttachingConnector,
+        com.sun.tools.jdi.SocketListeningConnector,
+        com.sun.tools.jdi.SunCommandLineLauncher;
 }
 
diff --git a/jdk/src/jdk.jdi/windows/classes/module-info.java.extra b/jdk/src/jdk.jdi/windows/classes/module-info.java.extra
index d048daa..e438e2c 100644
--- a/jdk/src/jdk.jdi/windows/classes/module-info.java.extra
+++ b/jdk/src/jdk.jdi/windows/classes/module-info.java.extra
@@ -23,5 +23,6 @@
  * questions.
  */
 
-provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.SharedMemoryAttachingConnector;
-provides com.sun.jdi.connect.Connector with com.sun.tools.jdi.SharedMemoryListeningConnector;
+provides com.sun.jdi.connect.Connector with
+    com.sun.tools.jdi.SharedMemoryAttachingConnector,
+    com.sun.tools.jdi.SharedMemoryListeningConnector;
diff --git a/jdk/src/jdk.jdwp.agent/share/classes/module-info.java b/jdk/src/jdk.jdwp.agent/share/classes/module-info.java
index c456bbc..ee7a047 100644
--- a/jdk/src/jdk.jdwp.agent/share/classes/module-info.java
+++ b/jdk/src/jdk.jdwp.agent/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Java Debug Wire Protocol.
+ */
 module jdk.jdwp.agent {
 }
 
diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c
index 20cd986..0477964 100644
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/ModuleReferenceImpl.c
@@ -83,36 +83,8 @@
     return JNI_TRUE;
 }
 
-static jboolean
-canRead(PacketInputStream *in, PacketOutputStream *out)
-{
-    static jmethodID method = NULL;
-    JNIEnv *env = getEnv();
-    jboolean can_read;
-    jobject module;
-    jobject source_module;
-
-    if (method == NULL) {
-        method = getMethod(env, jlrM(env), "canRead", "(Ljava/lang/reflect/Module;)Z");
-    }
-    module = inStream_readModuleRef(env, in);
-    if (inStream_error(in)) {
-        return JNI_TRUE;
-    }
-    source_module = inStream_readModuleRef(env, in);
-    if (inStream_error(in)) {
-        return JNI_TRUE;
-    }
-    can_read = JNI_FUNC_PTR(env, CallBooleanMethod)
-        (env, module, method, source_module);
-
-    (void)outStream_writeBoolean(out, can_read);
-    return JNI_TRUE;
-}
-
 
 void *ModuleReference_Cmds[] = { (void *)3
     ,(void *)getName
     ,(void *)getClassLoader
-    ,(void *)canRead
 };
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
index 5ec8f67..f9d1f81 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
@@ -268,7 +268,15 @@
                             resources.getStringTable());
                 }
             }
-            resPool = p.transform(resPool, resMgr.resourcePoolBuilder());
+            try {
+                resPool = p.transform(resPool, resMgr.resourcePoolBuilder());
+            } catch (PluginException pe) {
+                if (JlinkTask.DEBUG) {
+                    System.err.println("Plugin " + p.getName() + " threw exception during transform");
+                    pe.printStackTrace();
+                }
+                throw pe;
+            }
             if (resPool.isEmpty()) {
                 throw new Exception("Invalid resource pool for plugin " + p);
             }
@@ -444,6 +452,7 @@
                         res = res.copyWithContent(bytes);
                     } catch (IOException ex) {
                         if (JlinkTask.DEBUG) {
+                            System.err.println("IOException while reading resource: " + res.path());
                             ex.printStackTrace();
                         }
                         throw new PluginException(ex);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java
index 6ad2f8d..ecb63cd 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Jlink.java
@@ -298,7 +298,15 @@
         List<Plugin> bootPlugins = PluginRepository.getPlugins(Layer.boot());
         for (Plugin bp : bootPlugins) {
             if (Utils.isAutoEnabled(bp)) {
-                bp.configure(Collections.emptyMap());
+                try {
+                    bp.configure(Collections.emptyMap());
+                } catch (IllegalArgumentException e) {
+                    if (JlinkTask.DEBUG) {
+                        System.err.println("Plugin " + bp.getName() + " threw exception with config: {}");
+                        e.printStackTrace();
+                    }
+                    throw e;
+                }
                 plugins.add(bp);
             }
         }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
index 01876ee..4a5cbff 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java
@@ -29,6 +29,7 @@
 import java.io.PrintWriter;
 import java.io.UncheckedIOException;
 import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReference;
 import java.lang.module.ResolutionException;
@@ -191,6 +192,7 @@
                 taskHelper.showVersion(options.fullVersion);
                 return EXIT_OK;
             }
+
             if (taskHelper.getExistingImage() == null) {
                 if (options.modulePath.isEmpty()) {
                     throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true);
@@ -256,7 +258,6 @@
         ImageProvider imageProvider =
                 createImageProvider(finder,
                                     config.getModules(),
-                                    config.getLimitmods(),
                                     config.getByteOrder(),
                                     null,
                                     IGNORE_SIGNING_DEFAULT);
@@ -291,23 +292,43 @@
         postProcessImage(img, config.getPlugins());
     }
 
+    // the token for "all modules on the module path"
+    private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
     private void createImage() throws Exception {
         if (options.output == null) {
             throw taskHelper.newBadArgs("err.output.must.be.specified").showUsage(true);
         }
-        ModuleFinder finder
-                = newModuleFinder(options.modulePath, options.limitMods, options.addMods);
+
         if (options.addMods.isEmpty()) {
             throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
                     .showUsage(true);
         }
+
+        Set<String> roots = new HashSet<>();
+        for (String mod : options.addMods) {
+            if (mod.equals(ALL_MODULE_PATH)) {
+                ModuleFinder finder = modulePathFinder();
+                finder.findAll()
+                      .stream()
+                      .map(ModuleReference::descriptor)
+                      .map(ModuleDescriptor::name)
+                      .forEach(mn -> roots.add(mn));
+            } else {
+                roots.add(mod);
+            }
+        }
+
+        ModuleFinder finder = newModuleFinder(options.modulePath,
+                                              options.limitMods,
+                                              roots);
+
+
         // First create the image provider
         ImageProvider imageProvider = createImageProvider(finder,
-                        options.addMods,
-                        options.limitMods,
-                        options.endian,
-                        options.packagedModulesPath,
-                        options.ignoreSigning);
+                                                          roots,
+                                                          options.endian,
+                                                          options.packagedModulesPath,
+                                                          options.ignoreSigning);
 
         // Then create the Plugin Stack
         ImagePluginStack stack = ImagePluginConfiguration.
@@ -362,21 +383,20 @@
     }
 
     private static ImageProvider createImageProvider(ModuleFinder finder,
-                                                     Set<String> addMods,
-                                                     Set<String> limitMods,
+                                                     Set<String> roots,
                                                      ByteOrder order,
                                                      Path retainModulesPath,
                                                      boolean ignoreSigning)
             throws IOException
     {
-        if (addMods.isEmpty()) {
+        if (roots.isEmpty()) {
             throw new IllegalArgumentException("empty modules and limitmods");
         }
 
         Configuration cf = Configuration.empty()
                 .resolveRequires(finder,
                                  ModuleFinder.of(),
-                                 addMods);
+                                 roots);
 
         Map<String, Path> mods = cf.modules().stream()
             .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation));
@@ -388,8 +408,8 @@
      * modules, their transitive dependences, plus a set of other modules.
      */
     private static ModuleFinder limitFinder(ModuleFinder finder,
-            Set<String> roots,
-            Set<String> otherMods) {
+                                            Set<String> roots,
+                                            Set<String> otherMods) {
 
         // resolve all root modules
         Configuration cf = Configuration.empty()
@@ -535,40 +555,4 @@
             return image;
         }
     }
-
-    private static enum Section {
-        NATIVE_LIBS("native"),
-        NATIVE_CMDS("bin"),
-        CLASSES("classes"),
-        CONFIG("conf"),
-        UNKNOWN("unknown");
-
-        private final String jmodDir;
-
-        Section(String jmodDir) {
-            this.jmodDir = jmodDir;
-        }
-
-        String jmodDir() {
-            return jmodDir;
-        }
-
-        boolean matches(String path) {
-            return path.startsWith(jmodDir);
-        }
-
-        static Section getSectionFromName(String dir) {
-            if (Section.NATIVE_LIBS.matches(dir)) {
-                return Section.NATIVE_LIBS;
-            } else if (Section.NATIVE_CMDS.matches(dir)) {
-                return Section.NATIVE_CMDS;
-            } else if (Section.CLASSES.matches(dir)) {
-                return Section.CLASSES;
-            } else if (Section.CONFIG.matches(dir)) {
-                return Section.CONFIG;
-            } else {
-                return Section.UNKNOWN;
-            }
-        }
-    }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java
index 6a7af97..1d39c2c 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PluginRepository.java
@@ -74,7 +74,15 @@
         Objects.requireNonNull(pluginsLayer);
         Plugin plugin = getPlugin(name, pluginsLayer);
         if (plugin != null) {
-            plugin.configure(config);
+            try {
+                plugin.configure(config);
+            } catch (IllegalArgumentException e) {
+                if (JlinkTask.DEBUG) {
+                    System.err.println("Plugin " + plugin.getName() + " threw exception with config: " + config);
+                    e.printStackTrace();
+                }
+                throw e;
+            }
         }
         return plugin;
     }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java
index 11af53a..63ce3cd 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolConfiguration.java
@@ -50,24 +50,23 @@
         ModuleDescriptor md = mod.descriptor();
 
         // drop hashes
-        ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name());
+        ModuleDescriptor.Builder builder = ModuleDescriptor.module(md.name());
         md.requires().stream()
           .forEach(builder::requires);
         md.exports().stream()
           .forEach(builder::exports);
+        md.opens().stream()
+          .forEach(builder::opens);
         md.uses().stream()
           .forEach(builder::uses);
-        md.provides().values().stream()
+        md.provides().stream()
           .forEach(builder::provides);
 
         // build the proper concealed packages
-        Set<String> exps = md.exports().stream()
-            .map(ModuleDescriptor.Exports::source)
-            .collect(Collectors.toSet());
-
-        mod.packages().stream()
-           .filter(pn -> !exps.contains(pn))
-           .forEach(builder::conceals);
+        Set<String> concealed = new HashSet<>(mod.packages());
+        md.exports().stream().map(ModuleDescriptor.Exports::source).forEach(concealed::remove);
+        md.opens().stream().map(ModuleDescriptor.Opens::source).forEach(concealed::remove);
+        concealed.stream().forEach(builder::contains);
 
         md.version().ifPresent(builder::version);
         md.mainClass().ifPresent(builder::mainClass);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java
index 6647df0..06e7bce 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ResourcePoolManager.java
@@ -35,6 +35,7 @@
 import java.util.Set;
 import java.util.stream.Stream;
 import jdk.internal.jimage.decompressor.CompressedResourceHeader;
+import jdk.internal.loader.ResourceHelper;
 import jdk.tools.jlink.plugin.ResourcePool;
 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.ResourcePoolEntry;
@@ -58,6 +59,14 @@
         return ModuleDescriptor.read(bb);
     }
 
+    /**
+     * Returns true if a resource has an effective package.
+     */
+    public static boolean isNamedPackageResource(String path) {
+        return (path.endsWith(".class") && !path.endsWith("module-info.class")) ||
+                !ResourceHelper.isSimpleResource(path);
+    }
+
     class ResourcePoolModuleImpl implements ResourcePoolModule {
 
         final Map<String, ResourcePoolEntry> moduleContent = new LinkedHashMap<>();
@@ -100,7 +109,7 @@
                 .filter(m -> m.type() == ResourcePoolEntry.Type.CLASS_OR_RESOURCE)
                 .forEach(res -> {
                     String name = ImageFileCreator.resourceName(res.path());
-                    if (name.endsWith(".class") && !name.endsWith("module-info.class")) {
+                    if (isNamedPackageResource(name)) {
                         String pkg = ImageFileCreator.toPackage(name);
                         if (!pkg.isEmpty()) {
                             pkgs.add(pkg);
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
index e9b5d88..fc7d85f 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java
@@ -421,7 +421,15 @@
                 // we call configure once for each occurrence. It is upto the plugin
                 // to 'merge' and/or 'override' arguments.
                 for (Map<String, String> map : argsMaps) {
-                    plugin.configure(Collections.unmodifiableMap(map));
+                    try {
+                        plugin.configure(Collections.unmodifiableMap(map));
+                    } catch (IllegalArgumentException e) {
+                        if (JlinkTask.DEBUG) {
+                            System.err.println("Plugin " + plugin.getName() + " threw exception with config: " + map);
+                            e.printStackTrace();
+                        }
+                        throw e;
+                    }
                 }
 
                 if (!Utils.isDisabled(plugin)) {
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java
index ef497fe..b274226 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin.java
@@ -55,7 +55,7 @@
     public void configure(Map<String, String> config) {
         String arg = config.get(NAME);
         if (arg.isEmpty()) {
-            throw new PluginException("Section name must be specified");
+            throw new IllegalArgumentException("Section name must be specified");
         }
 
         switch (arg) {
@@ -66,7 +66,7 @@
                 filters.add(Type.HEADER_FILE);
                 break;
             default:
-                throw new PluginException("Invalid section name: " + arg);
+                throw new IllegalArgumentException("Invalid section name: " + arg);
         }
     }
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
index 0a18106..aa5660f 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OrderResourcesPlugin.java
@@ -26,6 +26,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.nio.file.FileSystem;
 import java.nio.file.Files;
 import java.nio.file.PathMatcher;
@@ -177,7 +178,7 @@
                     try {
                         lines = Files.readAllLines(file.toPath());
                     } catch (IOException ex) {
-                        throw new PluginException(ex);
+                        throw new UncheckedIOException(ex);
                     }
 
                     for (String line : lines) {
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
index 2da7943..823bf9f 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin.java
@@ -115,7 +115,7 @@
                 try (FileInputStream fis = new FileInputStream(operation)) {
                     props.load(fis);
                 } catch (IOException exp) {
-                    throw new RuntimeException(exp);
+                    throw new UncheckedIOException(exp);
                 }
                 props.forEach((k, v) -> release.put(k.toString(), v.toString()));
             }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java
index 349eefd..c72df27 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ResourceFilter.java
@@ -26,6 +26,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.PathMatcher;
@@ -35,7 +36,6 @@
 import java.util.Objects;
 import java.util.function.Predicate;
 import jdk.tools.jlink.internal.Utils;
-import jdk.tools.jlink.plugin.PluginException;
 
 /**
  *
@@ -62,7 +62,7 @@
                     try {
                         lines = Files.readAllLines(file.toPath());
                     } catch (IOException ex) {
-                        throw new PluginException(ex);
+                        throw new UncheckedIOException(ex);
                     }
 
                     lines.stream().forEach((line) -> {
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
index 7dd77fe..6be8c5f 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
@@ -28,17 +28,18 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.module.ModuleDescriptor.*;
 import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.*;
 import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
+import java.util.Objects;
 import java.util.Set;
-import java.util.stream.Collectors;
+import java.util.function.IntSupplier;
 
 import jdk.internal.misc.JavaLangModuleAccess;
 import jdk.internal.misc.SharedSecrets;
@@ -50,16 +51,17 @@
 import jdk.internal.org.objectweb.asm.Opcodes;
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ResourcePool;
 import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.Builder.*;
+import jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin.SystemModulesClassGenerator.*;
 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
 import jdk.tools.jlink.plugin.ResourcePoolEntry;
 
 /**
- * Jlink plugin to reconstitute module descriptors for installed modules.
- * It will extend module-info.class with ConcealedPackages attribute,
+ * Jlink plugin to reconstitute module descriptors for system modules.
+ * It will extend module-info.class with Packages attribute,
  * if not present. It also determines the number of packages of
  * the boot layer at link time.
  *
@@ -69,16 +71,14 @@
  * @see SystemModules
  */
 public final class SystemModuleDescriptorPlugin implements Plugin {
-    private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
+    private static final JavaLangModuleAccess JLMA =
+        SharedSecrets.getJavaLangModuleAccess();
 
-    // TODO: packager has the dependency on the plugin name
-    // Keep it as "--installed-modules" until packager removes such
-    // dependency (should not need to specify this plugin since it
-    // is enabled by default)
-    private static final String NAME = "installed-modules";
-    private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME);
+    private static final String NAME = "system-modules";
+    private static final String DESCRIPTION =
+        PluginsResourceBundle.getDescription(NAME);
+
     private boolean enabled;
-
     public SystemModuleDescriptorPlugin() {
         this.enabled = true;
     }
@@ -106,39 +106,38 @@
         }
     }
 
-
     @Override
     public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
         if (!enabled) {
             throw new PluginException(NAME + " was set");
         }
 
-        Builder builder = new Builder();
+        SystemModulesClassGenerator generator = new SystemModulesClassGenerator();
 
         // generate the byte code to create ModuleDescriptors
         // skip parsing module-info.class and skip name check
         in.moduleView().modules().forEach(module -> {
-            Optional<ResourcePoolEntry> optData = module.findEntry("module-info.class");
-            if (! optData.isPresent()) {
+
+            ResourcePoolEntry data = module.findEntry("module-info.class").orElseThrow(
                 // automatic module not supported yet
-                throw new PluginException("module-info.class not found for " +
-                                          module.name() + " module");
-            }
-            ResourcePoolEntry data = optData.get();
+                () ->  new PluginException("module-info.class not found for " +
+                    module.name() + " module")
+            );
+
             assert module.name().equals(data.moduleName());
             try {
                 ByteArrayInputStream bain = new ByteArrayInputStream(data.contentBytes());
                 ModuleDescriptor md = ModuleDescriptor.read(bain);
                 validateNames(md);
 
-                ModuleDescriptorBuilder mbuilder = builder.module(md, module.packages());
-                int packages = md.exports().size() + md.conceals().size();
-                if (md.conceals().isEmpty() &&
-                        packages != module.packages().size()) {
-                    // add ConcealedPackages attribute if not exist
+                Set<String> packages = module.packages();
+                generator.addModule(md, module.packages());
+
+                // add Packages attribute if not exist
+                if (md.packages().isEmpty() && packages.size() > 0) {
                     bain.reset();
                     ModuleInfoRewriter minfoWriter =
-                        new ModuleInfoRewriter(bain, mbuilder.conceals());
+                        new ModuleInfoRewriter(bain, module.packages());
                     // replace with the overridden version
                     data = data.copyWithContent(minfoWriter.getBytes());
                 }
@@ -149,11 +148,11 @@
         });
 
         // Generate the new class
-        ClassWriter cwriter = builder.build();
+        ClassWriter cwriter = generator.getClassWriter();
         in.entries().forEach(data -> {
             if (data.path().endsWith("module-info.class"))
                 return;
-            if (builder.isOverriddenClass(data.path())) {
+            if (generator.isOverriddenClass(data.path())) {
                 byte[] bytes = cwriter.toByteArray();
                 ResourcePoolEntry ndata = data.copyWithContent(bytes);
                 out.add(ndata);
@@ -166,14 +165,14 @@
     }
 
     /*
-     * Add ConcealedPackages attribute
+     * Add Packages attribute
      */
     class ModuleInfoRewriter extends ByteArrayOutputStream {
         final ModuleInfoExtender extender;
-        ModuleInfoRewriter(InputStream in, Set<String> conceals) throws IOException {
+        ModuleInfoRewriter(InputStream in, Set<String> packages) throws IOException {
             this.extender = ModuleInfoExtender.newExtender(in);
-            // Add ConcealedPackages attribute
-            this.extender.conceals(conceals);
+            // Add Packages attribute
+            this.extender.packages(packages);
             this.extender.write(this);
         }
 
@@ -190,19 +189,21 @@
         for (Exports e : md.exports()) {
             Checks.requirePackageName(e.source());
             if (e.isQualified())
-               e.targets().forEach(Checks::requireModuleName);
+                e.targets().forEach(Checks::requireModuleName);
         }
-        for (Map.Entry<String, Provides> e : md.provides().entrySet()) {
-            String service = e.getKey();
-            Provides provides = e.getValue();
-            Checks.requireServiceTypeName(service);
+        for (Opens opens : md.opens()) {
+            Checks.requirePackageName(opens.source());
+            if (opens.isQualified())
+                opens.targets().forEach(Checks::requireModuleName);
+        }
+        for (Provides provides : md.provides()) {
             Checks.requireServiceTypeName(provides.service());
             provides.providers().forEach(Checks::requireServiceProviderName);
         }
         for (String service : md.uses()) {
             Checks.requireServiceTypeName(service);
         }
-        for (String pn : md.conceals()) {
+        for (String pn : md.packages()) {
             Checks.requirePackageName(pn);
         }
     }
@@ -222,45 +223,60 @@
     }
 
     /**
-     * Builder of a new jdk.internal.module.SystemModules class
-     * to reconstitute ModuleDescriptor of the installed modules.
+     * ClassWriter of a new jdk.internal.module.SystemModules class
+     * to reconstitute ModuleDescriptor of the system modules.
      */
-    static class Builder {
+    static class SystemModulesClassGenerator {
         private static final String CLASSNAME =
             "jdk/internal/module/SystemModules";
         private static final String MODULE_DESCRIPTOR_BUILDER =
             "jdk/internal/module/Builder";
         private static final String MODULE_DESCRIPTOR_ARRAY_SIGNATURE =
             "[Ljava/lang/module/ModuleDescriptor;";
+        private static final String REQUIRES_MODIFIER_CLASSNAME =
+            "java/lang/module/ModuleDescriptor$Requires$Modifier";
+        private static final String EXPORTS_MODIFIER_CLASSNAME =
+            "java/lang/module/ModuleDescriptor$Exports$Modifier";
+        private static final String OPENS_MODIFIER_CLASSNAME =
+            "java/lang/module/ModuleDescriptor$Opens$Modifier";
 
         // static variables in SystemModules class
         private static final String MODULE_NAMES = "MODULE_NAMES";
         private static final String MODULES_TO_HASH = "MODULES_TO_HASH";
         private static final String PACKAGE_COUNT = "PACKAGES_IN_BOOT_LAYER";
 
-        private static final int BUILDER_VAR    = 0;
-        private static final int MD_VAR         = 1;   // variable for ModuleDescriptor
-        private static final int MODS_VAR       = 2;   // variable for Set<Modifier>
-        private static final int STRING_SET_VAR = 3;   // variable for Set<String>
         private static final int MAX_LOCAL_VARS = 256;
 
+        private final int BUILDER_VAR    = 0;
+        private final int MD_VAR         = 1;  // variable for ModuleDescriptor
+        private int nextLocalVar         = 2;  // index to next local variable
+
         private final ClassWriter cw;
         private MethodVisitor mv;
-        private int nextLocalVar = 4;
         private int nextModulesIndex = 0;
 
         // list of all ModuleDescriptorBuilders, invoked in turn when building.
         private final List<ModuleDescriptorBuilder> builders = new ArrayList<>();
 
         // module name to hash
-        private final Map<String, String> modulesToHash = new HashMap<>();
+        private final Map<String, byte[]> modulesToHash = new HashMap<>();
 
-        // map Set<String> to a specialized builder to allow them to be
-        // deduplicated as they are requested
-        private final Map<Set<String>, StringSetBuilder> stringSets = new HashMap<>();
+        // module name to index in MODULES_TO_HASH
+        private final Map<String, Integer> modulesToHashIndex = new HashMap<>();
 
-        public Builder() {
-            this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS+ClassWriter.COMPUTE_FRAMES);
+        // A builder to create one single Set instance for a given set of
+        // names or modifiers to reduce the footprint
+        // e.g. target modules of qualified exports
+        private final DedupSetBuilder dedupSetBuilder
+            = new DedupSetBuilder(this::getNextLocalVar);
+
+        public SystemModulesClassGenerator() {
+            this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS +
+                                      ClassWriter.COMPUTE_FRAMES);
+        }
+
+        private int getNextLocalVar() {
+            return nextLocalVar++;
         }
 
         /*
@@ -270,16 +286,16 @@
          */
         private void clinit(int numModules, int numPackages) {
             cw.visit(Opcodes.V1_8, ACC_PUBLIC+ACC_FINAL+ACC_SUPER, CLASSNAME,
-                    null, "java/lang/Object", null);
+                     null, "java/lang/Object", null);
 
             // public static String[] MODULE_NAMES = new String[] {....};
             cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, MODULE_NAMES,
                     "[Ljava/lang/String;", null, null)
                     .visitEnd();
 
-            // public static String[] MODULES_TO_HASH = new String[] {....};
+            // public static byte[][] MODULES_TO_HASH
             cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC, MODULES_TO_HASH,
-                "[Ljava/lang/String;", null, null)
+                "[[B", null, null)
                 .visitEnd();
 
             // public static int PACKAGES_IN_BOOT_LAYER;
@@ -308,23 +324,30 @@
 
             // create the MODULES_TO_HASH array
             pushInt(numModules);
-            mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+            mv.visitTypeInsn(ANEWARRAY, "[B");
 
             index = 0;
             for (ModuleDescriptorBuilder builder : builders) {
                 String mn = builder.md.name();
-                String recordedHash = modulesToHash.get(mn);
+                byte[] recordedHash = modulesToHash.get(mn);
                 if (recordedHash != null) {
                     mv.visitInsn(DUP);              // arrayref
                     pushInt(index);
-                    mv.visitLdcInsn(recordedHash);  // value
+                    pushInt(recordedHash.length);
+                    mv.visitIntInsn(NEWARRAY, T_BYTE);
+                    for (int i = 0; i < recordedHash.length; i++) {
+                        mv.visitInsn(DUP);              // arrayref
+                        pushInt(i);
+                        mv.visitIntInsn(BIPUSH, recordedHash[i]);
+                        mv.visitInsn(BASTORE);
+                    }
                     mv.visitInsn(AASTORE);
+                    modulesToHashIndex.put(mn, index);
                 }
                 index++;
             }
 
-            mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULES_TO_HASH,
-                    "[Ljava/lang/String;");
+            mv.visitFieldInsn(PUTSTATIC, CLASSNAME, MODULES_TO_HASH, "[[B");
 
             mv.visitInsn(RETURN);
             mv.visitMaxs(0, 0);
@@ -333,42 +356,42 @@
         }
 
         /*
-         * Adds the given ModuleDescriptor to the installed module list, and
-         * prepares mapping from Set<String> to StringSetBuilders to emit an
-         * optimized number of string sets during build.
+         * Adds the given ModuleDescriptor to the system module list, and
+         * prepares mapping from various Sets to SetBuilders to emit an
+         * optimized number of sets during build.
          */
-        public ModuleDescriptorBuilder module(ModuleDescriptor md, Set<String> packages) {
+        public void addModule(ModuleDescriptor md, Set<String> packages) {
             ModuleDescriptorBuilder builder = new ModuleDescriptorBuilder(md, packages);
             builders.add(builder);
 
             // exports
-            for (ModuleDescriptor.Exports e : md.exports()) {
-                if (e.isQualified()) {
-                    stringSets.computeIfAbsent(e.targets(), s -> new StringSetBuilder(s))
-                              .increment();
-                }
+            for (Exports e : md.exports()) {
+                dedupSetBuilder.stringSet(e.targets());
+                dedupSetBuilder.exportsModifiers(e.modifiers());
             }
 
-            // provides (preserve iteration order)
-            for (ModuleDescriptor.Provides p : md.provides().values()) {
-                stringSets.computeIfAbsent(p.providers(), s -> new StringSetBuilder(s, true))
-                          .increment();
+            // opens
+            for (Opens opens : md.opens()) {
+                dedupSetBuilder.stringSet(opens.targets());
+                dedupSetBuilder.opensModifiers(opens.modifiers());
+            }
+
+            // requires
+            for (Requires r : md.requires()) {
+                dedupSetBuilder.requiresModifiers(r.modifiers());
             }
 
             // uses
-            stringSets.computeIfAbsent(md.uses(), s -> new StringSetBuilder(s))
-                      .increment();
+            dedupSetBuilder.stringSet(md.uses());
 
             // hashes
             JLMA.hashes(md).ifPresent(mh -> modulesToHash.putAll(mh.hashes()));
-
-            return builder;
         }
 
         /*
          * Generate bytecode for SystemModules
          */
-        public ClassWriter build() {
+        public ClassWriter getClassWriter() {
             int numModules = builders.size();
             int numPackages = 0;
             for (ModuleDescriptorBuilder builder : builders) {
@@ -411,108 +434,79 @@
         }
 
         class ModuleDescriptorBuilder {
-            static final String REQUIRES_MODIFIER_CLASSNAME =
-                    "java/lang/module/ModuleDescriptor$Requires$Modifier";
-            static final String REQUIRES_MODIFIER_TYPE =
-                "Ljava/lang/module/ModuleDescriptor$Requires$Modifier;";
             static final String BUILDER_TYPE = "Ljdk/internal/module/Builder;";
-            static final String REQUIRES_MODIFIER_STRING_SIG =
-                "(" + REQUIRES_MODIFIER_TYPE + "Ljava/lang/String;)" + BUILDER_TYPE;
-            static final String STRING_SET_SIG =
-                "(Ljava/lang/String;Ljava/util/Set;)" + BUILDER_TYPE;
-            static final String SET_STRING_SIG =
-                "(Ljava/util/Set;Ljava/lang/String;)" + BUILDER_TYPE;
-            static final String SET_SIG =
-                "(Ljava/util/Set;)" + BUILDER_TYPE;
+            static final String EXPORTS_TYPE =
+                "Ljava/lang/module/ModuleDescriptor$Exports;";
+            static final String OPENS_TYPE =
+                "Ljava/lang/module/ModuleDescriptor$Opens;";
+            static final String PROVIDES_TYPE =
+                "Ljava/lang/module/ModuleDescriptor$Provides;";
+            static final String REQUIRES_TYPE =
+                "Ljava/lang/module/ModuleDescriptor$Requires;";
+
+            // method signature for static Builder::newExports, newOpens,
+            // newProvides, newRequires methods
+            static final String EXPORTS_MODIFIER_SET_STRING_SET_SIG =
+                "(Ljava/util/Set;Ljava/lang/String;Ljava/util/Set;)"
+                    + EXPORTS_TYPE;
+            static final String EXPORTS_MODIFIER_SET_STRING_SIG =
+                "(Ljava/util/Set;Ljava/lang/String;)" + EXPORTS_TYPE;
+            static final String OPENS_MODIFIER_SET_STRING_SET_SIG =
+                "(Ljava/util/Set;Ljava/lang/String;Ljava/util/Set;)"
+                    + OPENS_TYPE;
+            static final String OPENS_MODIFIER_SET_STRING_SIG =
+                "(Ljava/util/Set;Ljava/lang/String;)" + OPENS_TYPE;
+            static final String PROVIDES_STRING_LIST_SIG =
+                "(Ljava/lang/String;Ljava/util/List;)" + PROVIDES_TYPE;
+            static final String REQUIRES_SET_STRING_SIG =
+                "(Ljava/util/Set;Ljava/lang/String;)" + REQUIRES_TYPE;
+
+            // method signature for Builder instance methods that
+            // return this Builder instance
+            static final String EXPORTS_ARRAY_SIG =
+                "([" + EXPORTS_TYPE + ")" + BUILDER_TYPE;
+            static final String OPENS_ARRAY_SIG =
+                "([" + OPENS_TYPE + ")" + BUILDER_TYPE;
+            static final String PROVIDES_ARRAY_SIG =
+                "([" + PROVIDES_TYPE + ")" + BUILDER_TYPE;
+            static final String REQUIRES_ARRAY_SIG =
+                "([" + REQUIRES_TYPE + ")" + BUILDER_TYPE;
+            static final String SET_SIG = "(Ljava/util/Set;)" + BUILDER_TYPE;
             static final String STRING_SIG = "(Ljava/lang/String;)" + BUILDER_TYPE;
-            static final String STRING_STRING_SIG =
-                "(Ljava/lang/String;Ljava/lang/String;)" + BUILDER_TYPE;
+            static final String STRING_BYTE_ARRAY_SIG =
+                "(Ljava/lang/String;[B)" + BUILDER_TYPE;
+            static final String BOOLEAN_SIG = "(Z)" + BUILDER_TYPE;
+
 
             final ModuleDescriptor md;
             final Set<String> packages;
 
             ModuleDescriptorBuilder(ModuleDescriptor md, Set<String> packages) {
+                if (md.isAutomatic()) {
+                    throw new InternalError("linking automatic module is not supported");
+                }
                 this.md = md;
                 this.packages = packages;
             }
 
-            void newBuilder(String name, int reqs, int exports, int provides,
-                            int packages) {
-                mv.visitTypeInsn(NEW, MODULE_DESCRIPTOR_BUILDER);
-                mv.visitInsn(DUP);
-                mv.visitLdcInsn(name);
-                pushInt(initialCapacity(reqs));
-                pushInt(initialCapacity(exports));
-                pushInt(initialCapacity(provides));
-                pushInt(initialCapacity(packages));
-                mv.visitMethodInsn(INVOKESPECIAL, MODULE_DESCRIPTOR_BUILDER,
-                                   "<init>", "(Ljava/lang/String;IIII)V", false);
-                mv.visitVarInsn(ASTORE, BUILDER_VAR);
-                mv.visitVarInsn(ALOAD, BUILDER_VAR);
-            }
-
-            /*
-             * Returns the set of concealed packages from ModuleDescriptor, if present
-             * or compute it if the module does not have ConcealedPackages attribute
-             */
-            Set<String> conceals() {
-                Set<String> conceals = md.conceals();
-                if (conceals.isEmpty() && md.exports().size() != packages.size()) {
-                    Set<String> exports = md.exports().stream()
-                                            .map(Exports::source)
-                                            .collect(Collectors.toSet());
-                    conceals = packages.stream()
-                                       .filter(pn -> !exports.contains(pn))
-                                       .collect(Collectors.toSet());
-                }
-
-                if (conceals.size() + md.exports().size() != packages.size() &&
-                    // jdk.localedata may have concealed packages that don't exist
-                    !md.name().equals("jdk.localedata")) {
-                    throw new AssertionError(md.name() + ": conceals=" + conceals.size() +
-                            ", exports=" + md.exports().size() + ", packages=" + packages.size());
-                }
-                return conceals;
-            }
-
             void build() {
-                newBuilder(md.name(), md.requires().size(),
-                           md.exports().size(),
-                           md.provides().size(),
-                           packages.size());
+                // new jdk.internal.module.Builder
+                newBuilder();
 
                 // requires
-                for (ModuleDescriptor.Requires req : md.requires()) {
-                    switch (req.modifiers().size()) {
-                        case 0:
-                            requires(req.name());
-                            break;
-                        case 1:
-                            ModuleDescriptor.Requires.Modifier mod =
-                                req.modifiers().iterator().next();
-                            requires(mod, req.name());
-                            break;
-                        default:
-                            requires(req.modifiers(), req.name());
-                    }
-                }
+                requires(md.requires());
 
                 // exports
-                for (ModuleDescriptor.Exports e : md.exports()) {
-                    if (e.isQualified()) {
-                        exports(e.source(), e.targets());
-                    } else {
-                        exports(e.source());
-                    }
-                }
+                exports(md.exports());
+
+                // opens
+                opens(md.opens());
 
                 // uses
                 uses(md.uses());
 
                 // provides
-                for (ModuleDescriptor.Provides p : md.provides().values()) {
-                    provides(p.service(), p.providers());
-                }
+                provides(md.provides());
 
                 // all packages
                 packages(packages);
@@ -532,6 +526,38 @@
                 putModuleDescriptor();
             }
 
+            void newBuilder() {
+                mv.visitTypeInsn(NEW, MODULE_DESCRIPTOR_BUILDER);
+                mv.visitInsn(DUP);
+                mv.visitLdcInsn(md.name());
+                mv.visitMethodInsn(INVOKESPECIAL, MODULE_DESCRIPTOR_BUILDER,
+                    "<init>", "(Ljava/lang/String;)V", false);
+                mv.visitVarInsn(ASTORE, BUILDER_VAR);
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+
+                if (md.isOpen()) {
+                    setModuleBit("open", true);
+                }
+                if (md.isSynthetic()) {
+                    setModuleBit("synthetic", true);
+                }
+            }
+
+            /*
+             * Invoke Builder.<methodName>(boolean value)
+             */
+            void setModuleBit(String methodName, boolean value) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                if (value) {
+                    mv.visitInsn(ICONST_1);
+                } else {
+                    mv.visitInsn(ICONST_0);
+                }
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   methodName, BOOLEAN_SIG, false);
+                mv.visitInsn(POP);
+            }
+
             /*
              * Put ModuleDescriptor into the modules array
              */
@@ -539,130 +565,220 @@
                 mv.visitVarInsn(ALOAD, MD_VAR);
                 pushInt(nextModulesIndex++);
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                mv.visitLdcInsn(md.hashCode());
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                    "build", "()Ljava/lang/module/ModuleDescriptor;", false);
+                                   "build", "(I)Ljava/lang/module/ModuleDescriptor;",
+                                   false);
                 mv.visitInsn(AASTORE);
             }
 
             /*
-             * Invoke Builder.requires(String mn)
-             */
-            void requires(String name) {
-                mv.visitVarInsn(ALOAD, BUILDER_VAR);
-                mv.visitLdcInsn(name);
-                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                                   "requires", STRING_SIG, false);
-                mv.visitInsn(POP);
-            }
-
-            /*
-             * Invoke Builder.requires(Modifier mod, String mn)
-             */
-            void requires(ModuleDescriptor.Requires.Modifier mod, String name) {
-                mv.visitVarInsn(ALOAD, BUILDER_VAR);
-                mv.visitFieldInsn(GETSTATIC, REQUIRES_MODIFIER_CLASSNAME, mod.name(),
-                                  REQUIRES_MODIFIER_TYPE);
-                mv.visitLdcInsn(name);
-                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                                   "requires", REQUIRES_MODIFIER_STRING_SIG, false);
-                mv.visitInsn(POP);
-            }
-
-            /*
-             * Invoke Builder.requires(Set<Modifier> mods, String mn)
+             * Call Builder::newRequires to create Requires instances and
+             * then pass it to the builder by calling:
+             *      Builder.requires(Requires[])
              *
-             * EnumSet<Modifier> mods = EnumSet.of(mod,....);
-             * Buidler.requires(mods, mn);
              */
-            void requires(Set<ModuleDescriptor.Requires.Modifier> mods, String name) {
-                mv.visitVarInsn(ALOAD, MODS_VAR);
-                String signature = "(";
-                for (ModuleDescriptor.Requires.Modifier m : mods) {
-                    mv.visitFieldInsn(GETSTATIC, REQUIRES_MODIFIER_CLASSNAME, m.name(),
-                                      REQUIRES_MODIFIER_TYPE);
-                    signature += "Ljava/util/Enum;";
+            void requires(Set<Requires> requires) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                pushInt(requires.size());
+                mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Requires");
+                int arrayIndex = 0;
+                for (Requires require : requires) {
+                    mv.visitInsn(DUP);    // arrayref
+                    pushInt(arrayIndex++);
+                    newRequires(require.modifiers(), require.name());
+                    mv.visitInsn(AASTORE);
                 }
-                signature += ")Ljava/util/EnumSet;";
-                mv.visitMethodInsn(INVOKESTATIC, "java/util/EnumSet", "of",
-                                   signature, false);
-                mv.visitVarInsn(ASTORE, MODS_VAR);
-                mv.visitVarInsn(ALOAD, BUILDER_VAR);
-                mv.visitVarInsn(ALOAD, MODS_VAR);
-                mv.visitLdcInsn(name);
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                                   "requires", SET_STRING_SIG, false);
-                mv.visitInsn(POP);
+                                   "requires", REQUIRES_ARRAY_SIG, false);
             }
 
             /*
-             * Invoke Builder.exports(String pn)
+             * Invoke Builder.newRequires(Set<Modifier> mods, String mn)
+             *
+             * Set<Modifier> mods = ...
+             * Builder.newRequires(mods, mn);
              */
-            void exports(String pn) {
-                mv.visitVarInsn(ALOAD, BUILDER_VAR);
-
-                mv.visitLdcInsn(pn);
-                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                        "exports", STRING_SIG, false);
-                mv.visitInsn(POP);
+            void newRequires(Set<Requires.Modifier> mods, String name) {
+                int varIndex = dedupSetBuilder.indexOfRequiresModifiers(mods);
+                mv.visitVarInsn(ALOAD, varIndex);
+                mv.visitLdcInsn(name);
+                mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER,
+                                   "newRequires", REQUIRES_SET_STRING_SIG, false);
             }
 
             /*
-             * Invoke Builder.exports(String pn, Set<String> targets)
+             * Call Builder::newExports to create Exports instances and
+             * then pass it to the builder by calling:
+             *      Builder.exports(Exports[])
+             *
+             */
+            void exports(Set<Exports> exports) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                pushInt(exports.size());
+                mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Exports");
+                int arrayIndex = 0;
+                for (Exports export : exports) {
+                    mv.visitInsn(DUP);    // arrayref
+                    pushInt(arrayIndex++);
+                    newExports(export.modifiers(), export.source(), export.targets());
+                    mv.visitInsn(AASTORE);
+                }
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "exports", EXPORTS_ARRAY_SIG, false);
+            }
+
+            /*
+             * Invoke
+             *     Builder.newExports(Set<Exports.Modifier> ms, String pn,
+             *                        Set<String> targets)
+             * or
+             *     Builder.newExports(Set<Exports.Modifier> ms, String pn)
              *
              * Set<String> targets = new HashSet<>();
              * targets.add(t);
              * :
              * :
-             * Builder.exports(pn, targets);
+             *
+             * Set<Modifier> mods = ...
+             * Builder.newExports(mods, pn, targets);
              */
-            void exports(String pn, Set<String> targets) {
-                int varIndex = stringSets.get(targets).build();
+            void newExports(Set<Exports.Modifier> ms, String pn, Set<String> targets) {
+                int modifiersSetIndex = dedupSetBuilder.indexOfExportsModifiers(ms);
+                if (!targets.isEmpty()) {
+                    int stringSetIndex = dedupSetBuilder.indexOfStringSet(targets);
+                    mv.visitVarInsn(ALOAD, modifiersSetIndex);
+                    mv.visitLdcInsn(pn);
+                    mv.visitVarInsn(ALOAD, stringSetIndex);
+                    mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER,
+                        "newExports", EXPORTS_MODIFIER_SET_STRING_SET_SIG, false);
+                } else {
+                    mv.visitVarInsn(ALOAD, modifiersSetIndex);
+                    mv.visitLdcInsn(pn);
+                    mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER,
+                        "newExports", EXPORTS_MODIFIER_SET_STRING_SIG, false);
+                }
+            }
+
+
+            /**
+             * Call Builder::newOpens to create Opens instances and
+             * then pass it to the builder by calling:
+             *      Builder.opens(Opens[])
+             *
+             */
+            void opens(Set<Opens> opens) {
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
-                mv.visitLdcInsn(pn);
-                mv.visitVarInsn(ALOAD, varIndex);
+                pushInt(opens.size());
+                mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Opens");
+                int arrayIndex = 0;
+                for (Opens open : opens) {
+                    mv.visitInsn(DUP);    // arrayref
+                    pushInt(arrayIndex++);
+                    newOpens(open.modifiers(), open.source(), open.targets());
+                    mv.visitInsn(AASTORE);
+                }
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                                   "exports", STRING_SET_SIG, false);
-                mv.visitInsn(POP);
+                        "opens", OPENS_ARRAY_SIG, false);
             }
 
             /*
-             * Invokes Builder.uses(Set<String> uses)
+             * Invoke
+             *     Builder.newOpens(Set<Opens.Modifier> ms, String pn,
+             *                        Set<String> targets)
+             * or
+             *     Builder.newOpens(Set<Opens.Modifier> ms, String pn)
+             *
+             * Set<String> targets = new HashSet<>();
+             * targets.add(t);
+             * :
+             * :
+             *
+             * Set<Modifier> mods = ...
+             * Builder.newOpens(mods, pn, targets);
+             */
+            void newOpens(Set<Opens.Modifier> ms, String pn, Set<String> targets) {
+                int modifiersSetIndex = dedupSetBuilder.indexOfOpensModifiers(ms);
+                if (!targets.isEmpty()) {
+                    int stringSetIndex = dedupSetBuilder.indexOfStringSet(targets);
+                    mv.visitVarInsn(ALOAD, modifiersSetIndex);
+                    mv.visitLdcInsn(pn);
+                    mv.visitVarInsn(ALOAD, stringSetIndex);
+                    mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER,
+                            "newOpens", OPENS_MODIFIER_SET_STRING_SET_SIG, false);
+                } else {
+                    mv.visitVarInsn(ALOAD, modifiersSetIndex);
+                    mv.visitLdcInsn(pn);
+                    mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER,
+                            "newOpens", OPENS_MODIFIER_SET_STRING_SIG, false);
+                }
+            }
+
+            /*
+             * Invoke Builder.uses(Set<String> uses)
              */
             void uses(Set<String> uses) {
-                int varIndex = stringSets.get(uses).build();
+                int varIndex = dedupSetBuilder.indexOfStringSet(uses);
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
                 mv.visitVarInsn(ALOAD, varIndex);
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                        "uses", SET_SIG, false);
+                                   "uses", SET_SIG, false);
                 mv.visitInsn(POP);
             }
 
             /*
-             * Invoke Builder.provides(String service, Set<String> providers)
+            * Call Builder::newProvides to create Provides instances and
+            * then pass it to the builder by calling:
+            *      Builder.provides(Provides[] provides)
+            *
+            */
+            void provides(Collection<Provides> provides) {
+                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+                pushInt(provides.size());
+                mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Provides");
+                int arrayIndex = 0;
+                for (Provides provide : provides) {
+                    mv.visitInsn(DUP);    // arrayref
+                    pushInt(arrayIndex++);
+                    newProvides(provide.service(), provide.providers());
+                    mv.visitInsn(AASTORE);
+                }
+                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+                                   "provides", PROVIDES_ARRAY_SIG, false);
+            }
+
+            /*
+             * Invoke Builder.newProvides(String service, Set<String> providers)
              *
-             * Set<String> providers = new LinkedHashSet<>();
+             * Set<String> providers = new HashSet<>();
              * providers.add(impl);
              * :
              * :
-             * Builder.exports(service, providers);
+             * Builder.newProvides(service, providers);
              */
-            void provides(String service, Set<String> providers) {
-                int varIndex = stringSets.get(providers).build();
-                mv.visitVarInsn(ALOAD, BUILDER_VAR);
+            void newProvides(String service, List<String> providers) {
                 mv.visitLdcInsn(service);
-                mv.visitVarInsn(ALOAD, varIndex);
-                mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                                   "provides", STRING_SET_SIG, false);
-                mv.visitInsn(POP);
+                pushInt(providers.size());
+                mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+                int arrayIndex = 0;
+                for (String provider : providers) {
+                    mv.visitInsn(DUP);    // arrayref
+                    pushInt(arrayIndex++);
+                    mv.visitLdcInsn(provider);
+                    mv.visitInsn(AASTORE);
+                }
+                mv.visitMethodInsn(INVOKESTATIC, "java/util/List",
+                                   "of", "([Ljava/lang/Object;)Ljava/util/List;", true);
+                mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER,
+                                   "newProvides", PROVIDES_STRING_LIST_SIG, false);
             }
 
             /*
-             * Invoke Builder.conceals(String pn)
+             * Invoke Builder.packages(String pn)
              */
             void packages(Set<String> packages) {
+                int varIndex = dedupSetBuilder.newStringSet(packages);
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
-                int varIndex = new StringSetBuilder(packages).build();
-                assert varIndex == STRING_SET_VAR;
                 mv.visitVarInsn(ALOAD, varIndex);
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
                                    "packages", SET_SIG, false);
@@ -683,7 +799,7 @@
             /*
              * Invoke Builder.version(Version v);
              */
-            void version(ModuleDescriptor.Version v) {
+            void version(Version v) {
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
                 mv.visitLdcInsn(v.toString());
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
@@ -691,99 +807,277 @@
                 mv.visitInsn(POP);
             }
 
+            /*
+             * Invoke Builder.algorithm(String a);
+             */
             void algorithm(String alg) {
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
                 mv.visitLdcInsn(alg);
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                    "algorithm", STRING_SIG, false);
+                                   "algorithm", STRING_SIG, false);
                 mv.visitInsn(POP);
             }
 
-            void moduleHash(String name, String hashString) {
+            /*
+             * Invoke Builder.moduleHash(String name, byte[] hash);
+             */
+            void moduleHash(String name, byte[] hash) {
                 mv.visitVarInsn(ALOAD, BUILDER_VAR);
                 mv.visitLdcInsn(name);
-                mv.visitLdcInsn(hashString);
+
+                // must exist
+                Integer index = modulesToHashIndex.get(name);
+                if (index != null) {
+                    mv.visitFieldInsn(GETSTATIC, CLASSNAME, MODULES_TO_HASH, "[[B");
+                    pushInt(index);
+                    mv.visitInsn(AALOAD);
+                    assert(Objects.equals(hash, modulesToHash.get(name)));
+                } else {
+                    pushInt(hash.length);
+                    mv.visitIntInsn(NEWARRAY, T_BYTE);
+                    for (int i = 0; i < hash.length; i++) {
+                        mv.visitInsn(DUP);              // arrayref
+                        pushInt(i);
+                        mv.visitIntInsn(BIPUSH, hash[i]);
+                        mv.visitInsn(BASTORE);
+                    }
+                }
                 mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
-                    "moduleHash", STRING_STRING_SIG, false);
+                                   "moduleHash", STRING_BYTE_ARRAY_SIG, false);
                 mv.visitInsn(POP);
             }
         }
 
         /*
-         * StringSetBuilder generates bytecode to create one single instance
-         * of HashSet for a given set of names and assign to a local variable
-         * slot.  When there is only one single reference to a Set<String>,
-         * it will reuse STRING_SET_VAR for reference.  For Set<String> with
-         * multiple references, it will use a new local variable.
+         * Wraps set creation, ensuring identical sets are properly deduplicated.
          */
-        class StringSetBuilder {
-            final Set<String> names;
-            final boolean linked;
-            int refCount;
-            int localVarIndex;
+        class DedupSetBuilder {
+            // map Set<String> to a specialized builder to allow them to be
+            // deduplicated as they are requested
+            final Map<Set<String>, SetBuilder<String>> stringSets = new HashMap<>();
 
-            StringSetBuilder(Set<String> names, boolean linked) {
-                this.names = names;
-                this.linked = linked;
-            }
+            // map Set<Requires.Modifier> to a specialized builder to allow them to be
+            // deduplicated as they are requested
+            final Map<Set<Requires.Modifier>, EnumSetBuilder<Requires.Modifier>>
+                requiresModifiersSets = new HashMap<>();
 
-            StringSetBuilder(Set<String> names) {
-                this(names, false);
-            }
+            // map Set<Exports.Modifier> to a specialized builder to allow them to be
+            // deduplicated as they are requested
+            final Map<Set<Exports.Modifier>, EnumSetBuilder<Exports.Modifier>>
+                exportsModifiersSets = new HashMap<>();
 
-            void increment() {
-                refCount++;
+            // map Set<Opens.Modifier> to a specialized builder to allow them to be
+            // deduplicated as they are requested
+            final Map<Set<Opens.Modifier>, EnumSetBuilder<Opens.Modifier>>
+                opensModifiersSets = new HashMap<>();
+
+            private final int stringSetVar;
+            private final int enumSetVar;
+            private final IntSupplier localVarSupplier;
+
+            DedupSetBuilder(IntSupplier localVarSupplier) {
+                this.stringSetVar = localVarSupplier.getAsInt();
+                this.enumSetVar = localVarSupplier.getAsInt();
+                this.localVarSupplier = localVarSupplier;
             }
 
             /*
-             * Build bytecode for the Set<String> represented by this builder,
+             * Add the given set of strings to this builder.
+             */
+            void stringSet(Set<String> strings) {
+                stringSets.computeIfAbsent(strings,
+                    s -> new SetBuilder<>(s, stringSetVar, localVarSupplier)
+                ).increment();
+            }
+
+            /*
+             * Add the given set of Exports.Modifiers
+             */
+            void exportsModifiers(Set<Exports.Modifier> mods) {
+                exportsModifiersSets.computeIfAbsent(mods, s ->
+                                new EnumSetBuilder<>(s, EXPORTS_MODIFIER_CLASSNAME,
+                                        enumSetVar, localVarSupplier)
+                ).increment();
+            }
+
+            /*
+             * Add the given set of Opens.Modifiers
+             */
+            void opensModifiers(Set<Opens.Modifier> mods) {
+                opensModifiersSets.computeIfAbsent(mods, s ->
+                                new EnumSetBuilder<>(s, OPENS_MODIFIER_CLASSNAME,
+                                        enumSetVar, localVarSupplier)
+                ).increment();
+            }
+
+            /*
+             * Add the given set of Requires.Modifiers
+             */
+            void requiresModifiers(Set<Requires.Modifier> mods) {
+                requiresModifiersSets.computeIfAbsent(mods, s ->
+                    new EnumSetBuilder<>(s, REQUIRES_MODIFIER_CLASSNAME,
+                                         enumSetVar, localVarSupplier)
+                ).increment();
+            }
+
+            /*
+             * Retrieve the index to the given set of Strings. Emit code to
+             * generate it when SetBuilder::build is called.
+             */
+            int indexOfStringSet(Set<String> names) {
+                return stringSets.get(names).build();
+            }
+
+            /*
+             * Retrieve the index to the given set of Exports.Modifier.
+             * Emit code to generate it when EnumSetBuilder::build is called.
+             */
+            int indexOfExportsModifiers(Set<Exports.Modifier> mods) {
+                return exportsModifiersSets.get(mods).build();
+            }
+
+            /**
+             * Retrieve the index to the given set of Opens.Modifier.
+             * Emit code to generate it when EnumSetBuilder::build is called.
+             */
+            int indexOfOpensModifiers(Set<Opens.Modifier> mods) {
+                return opensModifiersSets.get(mods).build();
+            }
+
+
+            /*
+             * Retrieve the index to the given set of Requires.Modifier.
+             * Emit code to generate it when EnumSetBuilder::build is called.
+             */
+            int indexOfRequiresModifiers(Set<Requires.Modifier> mods) {
+                return requiresModifiersSets.get(mods).build();
+            }
+
+            /*
+             * Build a new string set without any attempt to deduplicate it.
+             */
+            int newStringSet(Set<String> names) {
+                int index = new SetBuilder<>(names, stringSetVar, localVarSupplier).build();
+                assert index == stringSetVar;
+                return index;
+            }
+        }
+
+        /*
+         * SetBuilder generates bytecode to create one single instance of Set
+         * for a given set of elements and assign to a local variable slot.
+         * When there is only one single reference to a Set<T>,
+         * it will reuse defaultVarIndex.  For a Set with multiple references,
+         * it will use a new local variable retrieved from the nextLocalVar
+         */
+        class SetBuilder<T> {
+            private final Set<T> elements;
+            private final int defaultVarIndex;
+            private final IntSupplier nextLocalVar;
+            private int refCount;
+            private int localVarIndex;
+
+            SetBuilder(Set<T> elements,
+                       int defaultVarIndex,
+                       IntSupplier nextLocalVar) {
+                this.elements = elements;
+                this.defaultVarIndex = defaultVarIndex;
+                this.nextLocalVar = nextLocalVar;
+            }
+
+            /*
+             * Increments the number of references to this particular set.
+             */
+            final void increment() {
+                refCount++;
+            }
+
+            /**
+             * Generate the appropriate instructions to load an object reference
+             * to the element onto the stack.
+             */
+            void visitElement(T element, MethodVisitor mv) {
+                mv.visitLdcInsn(element);
+            }
+
+            /*
+             * Build bytecode for the Set represented by this builder,
              * or get the local variable index of a previously generated set
              * (in the local scope).
              *
              * @return local variable index of the generated set.
              */
-            int build() {
+            final int build() {
                 int index = localVarIndex;
                 if (localVarIndex == 0) {
                     // if non-empty and more than one set reference this builder,
                     // emit to a unique local
-                    index = refCount <= 1 ? STRING_SET_VAR
-                                          : nextLocalVar++;
+                    index = refCount <= 1 ? defaultVarIndex
+                                          : nextLocalVar.getAsInt();
                     if (index < MAX_LOCAL_VARS) {
                         localVarIndex = index;
                     } else {
-                        // overflow: disable optimization and keep localVarIndex = 0
-                        index = STRING_SET_VAR;
+                        // overflow: disable optimization by using localVarIndex = 0
+                        index = defaultVarIndex;
                     }
 
-                    if (names.isEmpty()) {
-                        mv.visitMethodInsn(INVOKESTATIC, "java/util/Collections",
-                                "emptySet", "()Ljava/util/Set;", false);
-                        mv.visitVarInsn(ASTORE, index);
-                    } else if (names.size() == 1) {
-                        mv.visitLdcInsn(names.iterator().next());
-                        mv.visitMethodInsn(INVOKESTATIC, "java/util/Collections",
-                                "singleton", "(Ljava/lang/Object;)Ljava/util/Set;", false);
-                        mv.visitVarInsn(ASTORE, index);
-                    } else {
-                        String cn = linked ? "java/util/LinkedHashSet" : "java/util/HashSet";
-                        mv.visitTypeInsn(NEW, cn);
-                        mv.visitInsn(DUP);
-                        pushInt(initialCapacity(names.size()));
-                        mv.visitMethodInsn(INVOKESPECIAL, cn, "<init>", "(I)V", false);
-
-                        mv.visitVarInsn(ASTORE, index);
-                        for (String t : names) {
-                            mv.visitVarInsn(ALOAD, index);
-                            mv.visitLdcInsn(t);
-                            mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set",
-                                    "add", "(Ljava/lang/Object;)Z", true);
-                            mv.visitInsn(POP);
-                        }
-                    }
+                    generateSetOf(index);
                 }
                 return index;
             }
+
+            private void generateSetOf(int index) {
+                if (elements.size() <= 10) {
+                    // call Set.of(e1, e2, ...)
+                    StringBuilder sb = new StringBuilder("(");
+                    for (T t : elements) {
+                        sb.append("Ljava/lang/Object;");
+                        visitElement(t, mv);
+                    }
+                    sb.append(")Ljava/util/Set;");
+                    mv.visitMethodInsn(INVOKESTATIC, "java/util/Set",
+                            "of", sb.toString(), true);
+                } else {
+                    // call Set.of(E... elements)
+                    pushInt(elements.size());
+                    mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+                    int arrayIndex = 0;
+                    for (T t : elements) {
+                        mv.visitInsn(DUP);    // arrayref
+                        pushInt(arrayIndex);
+                        visitElement(t, mv);  // value
+                        mv.visitInsn(AASTORE);
+                        arrayIndex++;
+                    }
+                    mv.visitMethodInsn(INVOKESTATIC, "java/util/Set",
+                            "of", "([Ljava/lang/Object;)Ljava/util/Set;", true);
+                }
+                mv.visitVarInsn(ASTORE, index);
+            }
+        }
+
+        /*
+         * Generates bytecode to create one single instance of EnumSet
+         * for a given set of modifiers and assign to a local variable slot.
+         */
+        class EnumSetBuilder<T> extends SetBuilder<T> {
+
+            private final String className;
+
+            EnumSetBuilder(Set<T> modifiers, String className,
+                           int defaultVarIndex,
+                           IntSupplier nextLocalVar) {
+                super(modifiers, defaultVarIndex, nextLocalVar);
+                this.className = className;
+            }
+
+            /**
+             * Loads an Enum field.
+             */
+            void visitElement(T t, MethodVisitor mv) {
+                mv.visitFieldInsn(GETSTATIC, className, t.toString(),
+                                  "L" + className + ";");
+            }
         }
     }
 }
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties
index 52e4529..2bd58f6 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties
@@ -80,7 +80,7 @@
 Takes a file hinting to jlink what java.lang.invoke classes to pre-generate. If\n\
 this flag is not specified a default set of classes will be generated.
 
-installed-modules.description=Fast loading of module descriptors (always enabled)
+system-modules.description=Fast loading of module descriptors (always enabled)
 
 onoff.argument=<on|off>
 
diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
index e0d071d6..5d4b1d3 100644
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
@@ -40,6 +40,7 @@
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Version;
@@ -83,6 +84,7 @@
 import java.util.stream.Collectors;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
@@ -97,6 +99,7 @@
 import jdk.internal.joptsimple.OptionSet;
 import jdk.internal.joptsimple.OptionSpec;
 import jdk.internal.joptsimple.ValueConverter;
+import jdk.internal.loader.ResourceHelper;
 import jdk.internal.misc.JavaLangModuleAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.module.ModuleHashes;
@@ -261,9 +264,9 @@
         }
     }
 
-    static <T> String toString(Set<T> set) {
-        if (set.isEmpty()) { return ""; }
-        return set.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
+    static <T> String toString(Collection<T> c) {
+        if (c.isEmpty()) { return ""; }
+        return c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT))
                   .collect(joining(" "));
     }
 
@@ -291,14 +294,21 @@
             .sorted(Comparator.comparing(Exports::source))
             .forEach(p -> sb.append("\n  exports ").append(p));
 
-        md.conceals().stream().sorted()
-            .forEach(p -> sb.append("\n  conceals ").append(p));
+        md.opens().stream()
+            .sorted(Comparator.comparing(Opens::source))
+            .forEach(p -> sb.append("\n  opens ").append(p));
 
-        md.provides().values().stream()
+        Set<String> concealed = new HashSet<>(md.packages());
+        md.exports().stream().map(Exports::source).forEach(concealed::remove);
+        md.opens().stream().map(Opens::source).forEach(concealed::remove);
+        concealed.stream().sorted()
+                 .forEach(p -> sb.append("\n  contains ").append(p));
+
+        md.provides().stream()
             .sorted(Comparator.comparing(Provides::service))
             .forEach(p -> sb.append("\n  provides ").append(p.service())
-                .append(" with ")
-                .append(toString(p.providers())));
+                            .append(" with ")
+                            .append(toString(p.providers())));
 
         md.mainClass().ifPresent(v -> sb.append("\n  main-class " + v));
 
@@ -311,8 +321,8 @@
         JLMA.hashes(md).ifPresent(
             hashes -> hashes.names().stream().sorted().forEach(
                 mod -> sb.append("\n  hashes ").append(mod).append(" ")
-                    .append(hashes.algorithm()).append(" ")
-                    .append(hashes.hashFor(mod))));
+                         .append(hashes.algorithm()).append(" ")
+                         .append(hashes.hashFor(mod))));
 
         out.println(sb.toString());
     }
@@ -414,7 +424,7 @@
         /**
          * Writes the updated module-info.class to the ZIP output stream.
          *
-         * The updated module-info.class will have a ConcealedPackages attribute
+         * The updated module-info.class will have a Packages attribute
          * with the set of module-private/non-exported packages.
          *
          * If --module-version, --main-class, or other options were provided
@@ -439,15 +449,9 @@
             try (InputStream in = miSupplier.get()) {
                 ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
 
-                // Add (or replace) the ConcealedPackages attribute
+                // Add (or replace) the Packages attribute
                 if (packages != null) {
-                    Set<String> exported = descriptor.exports().stream()
-                        .map(ModuleDescriptor.Exports::source)
-                        .collect(Collectors.toSet());
-                    Set<String> concealed = packages.stream()
-                        .filter(p -> !exported.contains(p))
-                        .collect(Collectors.toSet());
-                    extender.conceals(concealed);
+                    extender.packages(packages);
                 }
 
                 // --main-class
@@ -556,10 +560,11 @@
         Set<String> findPackages(Path dir) {
             try {
                 return Files.find(dir, Integer.MAX_VALUE,
-                        ((path, attrs) -> attrs.isRegularFile() &&
-                                path.toString().endsWith(".class")))
-                        .map(path -> toPackageName(dir.relativize(path)))
-                        .filter(pkg -> pkg.length() > 0)   // module-info
+                                  ((path, attrs) -> attrs.isRegularFile()))
+                        .map(dir::relativize)
+                        .filter(path -> isResource(path.toString()))
+                        .map(path -> toPackageName(path))
+                        .filter(pkg -> pkg.length() > 0)
                         .distinct()
                         .collect(Collectors.toSet());
             } catch (IOException ioe) {
@@ -572,21 +577,30 @@
          */
         Set<String> findPackages(JarFile jf) {
             return jf.stream()
-                     .filter(e -> e.getName().endsWith(".class"))
+                     .filter(e -> !e.isDirectory() && isResource(e.getName()))
                      .map(e -> toPackageName(e))
-                     .filter(pkg -> pkg.length() > 0)   // module-info
+                     .filter(pkg -> pkg.length() > 0)
                      .distinct()
                      .collect(Collectors.toSet());
         }
 
+        /**
+         * Returns true if it's a .class or a resource with an effective
+         * package name.
+         */
+        boolean isResource(String name) {
+            name = name.replace(File.separatorChar, '/');
+            return name.endsWith(".class") || !ResourceHelper.isSimpleResource(name);
+        }
+
+
         String toPackageName(Path path) {
             String name = path.toString();
-            assert name.endsWith(".class");
             int index = name.lastIndexOf(File.separatorChar);
             if (index != -1)
                 return name.substring(0, index).replace(File.separatorChar, '.');
 
-            if (!name.equals(MODULE_INFO)) {
+            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
                 IOException e = new IOException(name  + " in the unnamed package");
                 throw new UncheckedIOException(e);
             }
@@ -595,12 +609,15 @@
 
         String toPackageName(ZipEntry entry) {
             String name = entry.getName();
-            assert name.endsWith(".class");
             int index = name.lastIndexOf("/");
             if (index != -1)
                 return name.substring(0, index).replace('/', '.');
-            else
-                return "";
+
+            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
+                IOException e = new IOException(name  + " in the unnamed package");
+                throw new UncheckedIOException(e);
+            }
+            return "";
         }
 
         void processClasses(JmodOutputStream out, List<Path> classpaths)
diff --git a/jdk/src/jdk.jlink/share/classes/module-info.java b/jdk/src/jdk.jlink/share/classes/module-info.java
index 37fced0..e20c763 100644
--- a/jdk/src/jdk.jlink/share/classes/module-info.java
+++ b/jdk/src/jdk.jlink/share/classes/module-info.java
@@ -31,21 +31,23 @@
 
     uses jdk.tools.jlink.plugin.Plugin;
 
-    provides java.util.spi.ToolProvider with jdk.tools.jmod.Main.JmodToolProvider;
-    provides java.util.spi.ToolProvider with jdk.tools.jlink.internal.Main.JlinkToolProvider;
+    provides java.util.spi.ToolProvider with
+        jdk.tools.jmod.Main.JmodToolProvider,
+        jdk.tools.jlink.internal.Main.JlinkToolProvider;
 
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludePlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ClassForNamePlugin;
+    provides jdk.tools.jlink.plugin.Plugin with
+        jdk.tools.jlink.internal.plugins.FileCopierPlugin,
+        jdk.tools.jlink.internal.plugins.StripDebugPlugin,
+        jdk.tools.jlink.internal.plugins.ExcludePlugin,
+        jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin,
+        jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin,
+        jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin,
+        jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin,
+        jdk.tools.jlink.internal.plugins.OrderResourcesPlugin,
+        jdk.tools.jlink.internal.plugins.DefaultCompressPlugin,
+        jdk.tools.jlink.internal.plugins.ExcludeVMPlugin,
+        jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin,
+        jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin,
+        jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin,
+        jdk.tools.jlink.internal.plugins.ClassForNamePlugin;
  }
diff --git a/jdk/src/jdk.jvmstat/share/classes/module-info.java b/jdk/src/jdk.jvmstat/share/classes/module-info.java
index d0038c2..fc82760 100644
--- a/jdk/src/jdk.jvmstat/share/classes/module-info.java
+++ b/jdk/src/jdk.jvmstat/share/classes/module-info.java
@@ -36,7 +36,8 @@
         jdk.jstatd;
 
     uses sun.jvmstat.monitor.MonitoredHostService;
-    provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService;
-    provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostLocalService;
+    provides sun.jvmstat.monitor.MonitoredHostService with
+        sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService,
+        sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostLocalService;
 }
 
diff --git a/jdk/src/jdk.localedata/share/classes/module-info.java b/jdk/src/jdk.localedata/share/classes/module-info.java
index 6af3dd7..324e14b 100644
--- a/jdk/src/jdk.localedata/share/classes/module-info.java
+++ b/jdk/src/jdk.localedata/share/classes/module-info.java
@@ -25,8 +25,7 @@
 
 module jdk.localedata {
     provides sun.util.locale.provider.LocaleDataMetaInfo with
-        sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo;
-    provides sun.util.locale.provider.LocaleDataMetaInfo with
+        sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo,
         sun.util.resources.provider.NonBaseLocaleDataMetaInfo;
     provides sun.util.resources.LocaleData.CommonResourceBundleProvider with
         sun.util.resources.provider.LocaleDataProvider;
diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java
index 6c6a8d9..13b979c 100644
--- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sr_Latn.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,8 +167,8 @@
             },
             { "NumberElements",
                 new String[] {
-                    ".",
                     ",",
+                    ".",
                     ";",
                     "%",
                     "0",
diff --git a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java
index f22ca8c..29e63d9 100644
--- a/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_sv.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -270,6 +270,13 @@
                     "e",
                 }
             },
+            { "NumberPatterns",
+                new String[] {
+                    "#,##0.###;-#,##0.###", // decimal pattern
+                    "\u00a4 #,##0.00;-\u00a4 #,##0.00", // currency pattern
+                    "#,##0 %" // percent pattern
+                }
+            },
             { "NumberElements",
                 new String[] {
                     ",", // decimal separator
diff --git a/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java b/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java
index 72e2870..69a8e94 100644
--- a/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java
+++ b/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java
@@ -238,9 +238,4 @@
         }
 
     }
-
-    // for sun.management.MappedMXBeanType
-    static CompositeData toCompositeData(VMOption option) {
-        return VMOptionCompositeData.toCompositeData(option);
-    }
 }
diff --git a/jdk/src/jdk.management/share/classes/module-info.java b/jdk/src/jdk.management/share/classes/module-info.java
index 34e371b..327d31e 100644
--- a/jdk/src/jdk.management/share/classes/module-info.java
+++ b/jdk/src/jdk.management/share/classes/module-info.java
@@ -24,7 +24,7 @@
  */
 
 module jdk.management {
-    requires public java.management;
+    requires transitive java.management;
 
     exports com.sun.management;
 
diff --git a/jdk/src/jdk.naming.dns/share/classes/module-info.java b/jdk/src/jdk.naming.dns/share/classes/module-info.java
index 1d367ee..abe26ec 100644
--- a/jdk/src/jdk.naming.dns/share/classes/module-info.java
+++ b/jdk/src/jdk.naming.dns/share/classes/module-info.java
@@ -26,8 +26,8 @@
 module jdk.naming.dns {
     requires java.naming;
 
-    exports com.sun.jndi.url.dns to
-        java.naming;
+    // temporary export until NamingManager.getURLContext uses services
+    exports com.sun.jndi.url.dns to java.naming;
 
     provides javax.naming.spi.InitialContextFactory
         with com.sun.jndi.dns.DnsContextFactory;
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericGroupPrincipal.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericGroupPrincipal.java
index f3183e3..0dcde2d 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericGroupPrincipal.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericGroupPrincipal.java
@@ -54,14 +54,7 @@
     private static final long serialVersionUID = 2345199581042573224L;
 
     private static final java.util.ResourceBundle rb =
-          java.security.AccessController.doPrivileged
-          (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
-              public java.util.ResourceBundle run() {
-                  return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources",
-                                sun.security.util.ResourcesMgr.class.getModule()));
-              }
-          });
+        java.util.ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     /**
      * @serial
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericUserPrincipal.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericUserPrincipal.java
index 858f956..806f621 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericUserPrincipal.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisNumericUserPrincipal.java
@@ -53,15 +53,7 @@
     private static final long serialVersionUID = -3178578484679887104L;
 
     private static final java.util.ResourceBundle rb =
-          java.security.AccessController.doPrivileged
-          (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
-              public java.util.ResourceBundle run() {
-                  return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources",
-                                 sun.security.util.ResourcesMgr.class.getModule()));
-              }
-           });
-
+        java.util.ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     /**
      * @serial
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisPrincipal.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisPrincipal.java
index 6cbc103..f4491db 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisPrincipal.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/SolarisPrincipal.java
@@ -51,14 +51,7 @@
     private static final long serialVersionUID = -7840670002439379038L;
 
     private static final java.util.ResourceBundle rb =
-          java.security.AccessController.doPrivileged
-          (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
-              public java.util.ResourceBundle run() {
-                  return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources",
-                                 sun.security.util.ResourcesMgr.class.getModule()));
-              }
-          });
+        java.util.ResourceBundle.getBundle("sun.security.util.AuthResources");
 
 
     /**
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/X500Principal.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/X500Principal.java
index 1bf2e3e..a3a04a0 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/X500Principal.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/X500Principal.java
@@ -56,14 +56,7 @@
     private static final long serialVersionUID = -8222422609431628648L;
 
     private static final java.util.ResourceBundle rb =
-        java.security.AccessController.doPrivileged
-        (new java.security.PrivilegedAction<java.util.ResourceBundle>() {
-              public java.util.ResourceBundle run() {
-                  return (java.util.ResourceBundle.getBundle
-                                ("sun.security.util.AuthResources",
-                                 sun.security.util.ResourcesMgr.class.getModule()));
-              }
-        });
+        java.util.ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     /**
      * @serial
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java
index 24eb622..4e02253 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java
@@ -153,15 +153,8 @@
  */
 public class JndiLoginModule implements LoginModule {
 
-    private static final ResourceBundle rb = AccessController.doPrivileged(
-            new PrivilegedAction<ResourceBundle>() {
-                public ResourceBundle run() {
-                    return ResourceBundle.getBundle(
-                            "sun.security.util.AuthResources",
-                            sun.security.util.ResourcesMgr.class.getModule());
-                }
-            }
-    );
+    private static final ResourceBundle rb =
+        ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     /** JNDI Provider */
     public final String USER_PROVIDER = "user.provider.url";
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java
index b79d6cc..34f9839 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java
@@ -112,15 +112,8 @@
  */
 public class KeyStoreLoginModule implements LoginModule {
 
-    private static final ResourceBundle rb = AccessController.doPrivileged(
-            new PrivilegedAction<ResourceBundle>() {
-                public ResourceBundle run() {
-                    return ResourceBundle.getBundle(
-                            "sun.security.util.AuthResources",
-                            sun.security.util.ResourcesMgr.class.getModule());
-                }
-            }
-    );
+    private static final ResourceBundle rb =
+        ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     /* -- Fields -- */
 
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
index d59e2a8..2aa1e8a 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
@@ -419,15 +419,8 @@
 
     private static final String NAME = "javax.security.auth.login.name";
     private static final String PWD = "javax.security.auth.login.password";
-    private static final ResourceBundle rb = AccessController.doPrivileged(
-            new PrivilegedAction<ResourceBundle>() {
-                public ResourceBundle run() {
-                    return ResourceBundle.getBundle(
-                            "sun.security.util.AuthResources",
-                            sun.security.util.ResourcesMgr.class.getModule());
-                }
-            }
-    );
+    private static final ResourceBundle rb =
+        ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     /**
      * Initialize this {@code LoginModule}.
diff --git a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/LdapLoginModule.java b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/LdapLoginModule.java
index 29db6c3..ff60810 100644
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/LdapLoginModule.java
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/LdapLoginModule.java
@@ -306,15 +306,8 @@
 public class LdapLoginModule implements LoginModule {
 
     // Use the default classloader for this class to load the prompt strings.
-    private static final ResourceBundle rb = AccessController.doPrivileged(
-            new PrivilegedAction<ResourceBundle>() {
-                public ResourceBundle run() {
-                    return ResourceBundle.getBundle(
-                        "sun.security.util.AuthResources",
-                        sun.security.util.ResourcesMgr.class.getModule());
-                }
-            }
-        );
+    private static final ResourceBundle rb =
+        ResourceBundle.getBundle("sun.security.util.AuthResources");
 
     // Keys to retrieve the stored username and password
     private static final String USERNAME_KEY = "javax.security.auth.login.name";
diff --git a/jdk/src/jdk.security.auth/share/classes/module-info.java b/jdk/src/jdk.security.auth/share/classes/module-info.java
index 8f97ca4..5181d23 100644
--- a/jdk/src/jdk.security.auth/share/classes/module-info.java
+++ b/jdk/src/jdk.security.auth/share/classes/module-info.java
@@ -28,24 +28,22 @@
  * various authentication modules.
  */
 module jdk.security.auth {
-    requires public java.naming;
+    requires transitive java.naming;
     requires java.security.jgss;
 
     exports com.sun.security.auth;
     exports com.sun.security.auth.callback;
     exports com.sun.security.auth.login;
     exports com.sun.security.auth.module;
+
+    uses sun.security.util.AuthResourcesProvider;
+
     provides javax.security.auth.spi.LoginModule with
-        com.sun.security.auth.module.Krb5LoginModule;
-    provides javax.security.auth.spi.LoginModule with
-        com.sun.security.auth.module.UnixLoginModule;
-    provides javax.security.auth.spi.LoginModule with
-        com.sun.security.auth.module.JndiLoginModule;
-    provides javax.security.auth.spi.LoginModule with
-        com.sun.security.auth.module.KeyStoreLoginModule;
-    provides javax.security.auth.spi.LoginModule with
-        com.sun.security.auth.module.LdapLoginModule;
-    provides javax.security.auth.spi.LoginModule with
+        com.sun.security.auth.module.Krb5LoginModule,
+        com.sun.security.auth.module.UnixLoginModule,
+        com.sun.security.auth.module.JndiLoginModule,
+        com.sun.security.auth.module.KeyStoreLoginModule,
+        com.sun.security.auth.module.LdapLoginModule,
         com.sun.security.auth.module.NTLoginModule;
 }
 
diff --git a/jdk/src/jdk.security.jgss/share/classes/module-info.java b/jdk/src/jdk.security.jgss/share/classes/module-info.java
index 9701e2a..e66017f 100644
--- a/jdk/src/jdk.security.jgss/share/classes/module-info.java
+++ b/jdk/src/jdk.security.jgss/share/classes/module-info.java
@@ -28,7 +28,7 @@
  * GSSAPI mechanism.
  */
 module jdk.security.jgss {
-    requires public java.security.jgss;
+    requires transitive java.security.jgss;
     requires java.logging;
     requires java.security.sasl;
     exports com.sun.security.jgss;
diff --git a/jdk/src/jdk.unsupported/share/classes/module-info.java b/jdk/src/jdk.unsupported/share/classes/module-info.java
index 5ad2487..7cd9691 100644
--- a/jdk/src/jdk.unsupported/share/classes/module-info.java
+++ b/jdk/src/jdk.unsupported/share/classes/module-info.java
@@ -27,5 +27,8 @@
     exports sun.misc;
     exports sun.reflect;
     exports com.sun.nio.file;
+
+    opens sun.misc;
+    opens sun.reflect;
 }
 
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index b42555a..441ef67 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -145,10 +145,17 @@
 
 ############################################################################
 
-# jdk_jmx
+# jdk_management
 
 com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all
 com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java  8030957 aix-all
+
+com/sun/management/DiagnosticCommandMBean/DcmdMBeanPermissionsTest.java 8169575 generic-all
+
+############################################################################
+
+# jdk_jmx
+
 javax/management/MBeanServer/OldMBeanServerTest.java            8030957 aix-all
 
 javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java 8042215 generic-all
@@ -227,8 +234,6 @@
 
 javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all
 
-javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java 8168881 generic-all
-
 ############################################################################
 
 # jdk_imageio
@@ -306,4 +311,8 @@
 
 com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java                   8169942 linux-i586,macosx-all,windows-x64
 
+javax/rmi/PortableRemoteObject/8146975/RmiIiopReturnValueTest.java 8169737 linux-all
+
+javax/xml/ws/clientjar/TestWsImport.java			8170370 generic-all
+
 ############################################################################
diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT
index 1e70348..c61b9bc 100644
--- a/jdk/test/TEST.ROOT
+++ b/jdk/test/TEST.ROOT
@@ -26,8 +26,8 @@
 # Allow querying of various System properties in @requires clauses
 requires.properties=sun.arch.data.model java.runtime.name
 
-# Tests using jtreg 4.2 b03 features
-requiredVersion=4.2 b03
+# Tests using jtreg 4.2 b04 features
+requiredVersion=4.2 b04
 
 # Path to libraries in the topmost test directory. This is needed so @library
 # does not need ../../ notation to reach them
diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups
index def84c8..448f871 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -741,7 +741,8 @@
   java/util/ResourceBundle/Bug6359330.java  \
   java/util/Spliterator/SpliteratorCharacteristics.java  \
   java/util/Spliterator/SpliteratorCollisions.java  \
-  java/util/Spliterator/SpliteratorLateBindingFailFastTest.java  \
+  java/util/Spliterator/SpliteratorLateBindingTest.java  \
+  java/util/Spliterator/SpliteratorFailFastTest.java  \
   java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java  \
   java/util/StringJoiner/MergeTest.java  \
   java/util/StringJoiner/StringJoinerTest.java  \
diff --git a/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java
index 6aebc55..17cd517 100644
--- a/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java
@@ -62,9 +62,10 @@
  * @test
  * @library /test/lib
  * @build jdk.test.lib.*
- * @compile  ObjectStreamTest.java  ObjectStreamTest$_Echo_Stub.java
- *           ObjectStreamTest$_Server_Tie.java
- * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io
+ * @compile ObjectStreamTest.java  ObjectStreamTest$_Echo_Stub.java
+ *          ObjectStreamTest$_Server_Tie.java
+ * @modules java.base/java.io:open
+ *          java.corba/com.sun.corba.se.impl.io:+open
  *          java.corba/com.sun.corba.se.impl.activation
  * @summary Tests of ReflectionFactory use in IIOP Serialization
  * @run testng/othervm ObjectStreamTest
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/Dynamic.java b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/Dynamic.java
index 3aa6d29..91d7426 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/Dynamic.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestAESCiphers/Dynamic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -150,19 +150,8 @@
             int offset = ci.update(plainText, 0, plainText.length, cipherText,
                     0);
             ci.doFinal(cipherText, offset);
+            ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
 
-            if (!mo.equalsIgnoreCase("ECB")) {
-                iv = ci.getIV();
-                aps = new IvParameterSpec(iv);
-            } else {
-                aps = null;
-            }
-
-            if (!mo.equalsIgnoreCase("GCM")) {
-                ci.init(Cipher.DECRYPT_MODE, key, aps);
-            } else {
-                ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
-            }
             byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
             int len = ci.doFinal(cipherText, 0, cipherText.length,
                     recoveredText);
@@ -174,12 +163,14 @@
 
             result = Arrays.equals(plainText, tmp);
         } catch (NoSuchAlgorithmException nsaEx) {
-            nsaEx.printStackTrace();
             // CFB7 and OFB150 are negative test,SunJCE not support this
             // algorithm
             result = mo.equalsIgnoreCase("CFB7")
                     || mo.equalsIgnoreCase("OFB150");
-
+            if (!result) {
+                // only report unexpected exception
+                nsaEx.printStackTrace();
+            }
         }
         return result;
     }
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java
index e58acb2..71e01a4 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/AES/TestGHASH.java
@@ -25,7 +25,7 @@
 /*
  * @test
  * @bug 8069072
- * @modules java.base/com.sun.crypto.provider
+ * @modules java.base/com.sun.crypto.provider:open
  * @summary Test vectors for com.sun.crypto.provider.GHASH.
  *
  * Single iteration to verify software-only GHASH algorithm.
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java b/jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java
index 7006abc..1fae3a0 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/Blowfish/TestCipherBlowfish.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
                     "OFB", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40", "OFB48", "OFB56",
                     "OFB64"},
                 new String[]{"NoPaDDing", "PKCS5Padding"},
-                true);
+                32, 448);
     }
 
     public static void main(String[] args) throws Exception {
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java
index 324d804..1f12f88 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java
@@ -24,7 +24,8 @@
 /**
  * @test
  * @bug 8151149
- * @modules java.base/com.sun.crypto.provider
+ * @modules java.base/javax.crypto:open
+ *          java.base/com.sun.crypto.provider:+open
  */
 
 import java.lang.reflect.*;
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/NegativeLength.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/NegativeLength.java
index 0408d75..9c4cc36 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/NegativeLength.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/NegativeLength.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 8001596
+ * @modules java.base/javax.crypto.spec:open
  * @summary Incorrect condition check in PBKDF2KeyImpl.java
  */
 
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/AESPBEWrapper.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/AESPBEWrapper.java
index 16dd69a..b166fc1 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/AESPBEWrapper.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/AESPBEWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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
@@ -24,6 +24,7 @@
 import java.io.PrintStream;
 import java.security.AlgorithmParameters;
 import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
 import javax.crypto.Cipher;
 import javax.crypto.SecretKeyFactory;
@@ -69,6 +70,15 @@
      */
     @Override
     public boolean execute(int edMode, byte[] inputText, int offset, int len) {
+        boolean isUnlimited;
+        try {
+            isUnlimited =
+                (Cipher.getMaxAllowedKeyLength(this.algo) == Integer.MAX_VALUE);
+        } catch (NoSuchAlgorithmException nsae) {
+            out.println("Got unexpected exception for " + this.algo);
+            nsae.printStackTrace(out);
+            return false;
+        }
         try {
             // init Cipher
             if (Cipher.ENCRYPT_MODE == edMode) {
@@ -78,6 +88,11 @@
                 ci.init(Cipher.DECRYPT_MODE, this.key, pbeParams);
             }
 
+            if (this.algo.endsWith("AES_256") && !isUnlimited) {
+                out.print("Expected exception not thrown for " + this.algo);
+                return false;
+            }
+
             // First, generate the cipherText at an allocated buffer
             byte[] outputText = ci.doFinal(inputText, offset, len);
 
@@ -86,29 +101,19 @@
             int off = ci.update(inputText, offset, len, inputText, myoff);
             ci.doFinal(inputText, myoff + off);
 
-            if (this.algo.endsWith("AES_256")) {
-                out.print("Expected exception uncaught, "
-                        + "keyStrength > 128 within " + this.algo);
-
-                return false;
-            }
-
             // Compare to see whether the two results are the same or not
             return equalsBlock(inputText, myoff, outputText, 0,
                     outputText.length);
         } catch (Exception ex) {
             if ((ex instanceof InvalidKeyException)
-                    && this.algo.endsWith("AES_256")) {
-                out.println("Expected InvalidKeyException exception: "
-                        + ex.getMessage());
-
+                    && this.algo.endsWith("AES_256") && !isUnlimited) {
+                out.println("Expected InvalidKeyException thrown");
                 return true;
+            } else {
+                out.println("Got unexpected exception for " + algo);
+                ex.printStackTrace(out);
+                return false;
             }
-
-            out.println("Catch unexpected exception within " + algo);
-            ex.printStackTrace(out);
-
-            return false;
         }
     }
 }
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBECipherWrapper.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBECipherWrapper.java
index e4a8509..6a61ca0 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBECipherWrapper.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/PBESameBuffer/PBECipherWrapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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
@@ -32,6 +32,7 @@
 import java.util.StringTokenizer;
 
 import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
 
 import java.io.PrintStream;
@@ -64,9 +65,25 @@
         StringTokenizer st = new StringTokenizer(algo, "/");
         String baseAlgo = st.nextToken().toUpperCase();
 
+        boolean isUnlimited;
+        try {
+            isUnlimited =
+                (Cipher.getMaxAllowedKeyLength(this.algo) == Integer.MAX_VALUE);
+        } catch (NoSuchAlgorithmException nsae) {
+            out.println("Got unexpected exception for " + this.algo);
+            nsae.printStackTrace(out);
+            return false;
+        }
+
         // Perform encryption or decryption depends on the specified edMode
         try {
             ci.init(edMode, key, aps);
+            if ((baseAlgo.endsWith("TRIPLEDES")
+                    || baseAlgo.endsWith("AES_256")) && !isUnlimited) {
+                out.print("Expected InvalidKeyException not thrown: "
+                    + this.algo);
+                return false;
+            }
 
             // First, generate the cipherText at an allocated buffer
             byte[] outputText = ci.doFinal(inputText, offset, len);
@@ -78,33 +95,24 @@
 
             ci.doFinal(inputText, myoff + off);
 
-            if (baseAlgo.endsWith("TRIPLEDES")
-                    || baseAlgo.endsWith("AES_256")) {
-                out.print("Expected exception uncaught,"
-                        + "keyStrength > 128 within " + this.algo);
-
-                return false;
-            }
-
             // Compare to see whether the two results are the same or not
             boolean result = equalsBlock(inputText, myoff, outputText, 0,
                     outputText.length);
 
             return result;
         } catch (Exception ex) {
-            if ((ex instanceof InvalidKeyException)
-                    && (baseAlgo.endsWith("TRIPLEDES")
-                    || baseAlgo.endsWith("AES_256"))) {
-                out.println("Expected InvalidKeyException exception: "
-                        + ex.getMessage());
-
+            if ((ex instanceof InvalidKeyException) &&
+                    (baseAlgo.endsWith("TRIPLEDES")
+                        || baseAlgo.endsWith("AES_256")) &&
+                !isUnlimited) {
+                out.println("Expected InvalidKeyException thrown for "
+                    + algo);
                 return true;
+            } else {
+                out.println("Got unexpected exception for " + algo);
+                ex.printStackTrace(out);
+                return false;
             }
-
-            out.println("Catch unexpected exception within " + algo);
-            ex.printStackTrace(out);
-
-            return false;
         }
     }
 }
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherKeyWrapperPBEKey.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherKeyWrapperPBEKey.java
index dd767ba..437b8ff 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherKeyWrapperPBEKey.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherKeyWrapperPBEKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014, 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
@@ -120,6 +120,9 @@
                 = new StringTokenizer(algo, "/").nextToken().toUpperCase();
         boolean isAES = baseAlgo.contains("AES");
 
+        boolean isUnlimited =
+            (Cipher.getMaxAllowedKeyLength(algo) == Integer.MAX_VALUE);
+
         try {
             // Initialization
             new Random().nextBytes(salt);
@@ -129,7 +132,6 @@
             SecretKey key = skf.generateSecret(new PBEKeySpec(
                     "Secret Key".toCharArray()));
             Cipher ci = Cipher.getInstance(algo);
-
             if (isAES) {
                 ci.init(Cipher.WRAP_MODE, key);
                 pbeParams = ci.getParameters();
@@ -146,10 +148,10 @@
 
             Key unwrappedKey = ci.unwrap(keyWrapper, algo, Cipher.SECRET_KEY);
 
-            if (baseAlgo.endsWith("TRIPLEDES")
-                    || baseAlgo.endsWith("AES_256")) {
+            if ((baseAlgo.endsWith("TRIPLEDES")
+                    || baseAlgo.endsWith("AES_256")) && !isUnlimited) {
                 out.print(
-                        "InvalidKeyException not thrown when keyStrength > 128");
+                        "Expected InvalidKeyException not thrown");
                 return false;
             }
 
@@ -158,8 +160,9 @@
         } catch (InvalidKeyException ex) {
 
             if ((baseAlgo.endsWith("TRIPLEDES")
-                    || baseAlgo.endsWith("AES_256"))) {
-                out.println("Expected InvalidKeyException, keyStrength > 128");
+                    || baseAlgo.endsWith("AES_256")) && !isUnlimited) {
+                out.print(
+                        "Expected InvalidKeyException thrown");
                 return true;
             } else {
                 throw ex;
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java
index f304989..97a52c9 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/TestCipherPBE.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,6 +79,9 @@
 
         out.println("=> Testing: " + algorithm);
 
+        boolean isUnlimited =
+            (Cipher.getMaxAllowedKeyLength(algorithm) == Integer.MAX_VALUE);
+
         try {
             // Initialization
             AlgorithmParameterSpec algoParamSpec
@@ -98,9 +101,9 @@
             ci.init(Cipher.DECRYPT_MODE, secretKey, algoParamSpec);
             byte[] recoveredText = ci.doFinal(cipherText);
 
-            if (algorithm.contains("TripleDES")) {
+            if (algorithm.contains("TripleDES") && !isUnlimited) {
                 throw new RuntimeException(
-                        "Expected InvalidKeyException exception uncaugh");
+                        "Expected InvalidKeyException not thrown");
             }
 
             // Comparison
@@ -110,8 +113,8 @@
             }
             out.println("Test Passed.");
         } catch (InvalidKeyException ex) {
-            if (algorithm.contains("TripleDES")) {
-                out.println("Expected InvalidKeyException raised");
+            if (algorithm.contains("TripleDES") && !isUnlimited) {
+                out.println("Expected InvalidKeyException thrown");
             } else {
                 throw new RuntimeException(ex);
             }
diff --git a/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java b/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java
index 9cb25c7..b5e50c8 100644
--- a/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java
+++ b/jdk/test/com/sun/crypto/provider/Cipher/TestCipher.java
@@ -49,14 +49,13 @@
     private final String[] MODES;
     private final String[] PADDINGS;
 
-    /* Used to test cipher with different key strengths
-       Key size tested is increment of KEYCUTTER from MINIMUM_KEY_SIZE to
-       maximum allowed keysize.
-       DES/DESede/Blowfish work with currently selected key sizes.
+    /* Used to test variable-key-length ciphers:
+       Key size tested is increment of KEYCUTTER from minKeySize
+       to min(maxKeySize, Cipher.getMaxAllowedKeyLength(algo)).
     */
-    private final int variousKeySize;
     private final int KEYCUTTER = 8;
-    private final int MINIMUM_KEY_SIZE = 32;
+    private final int minKeySize;
+    private final int maxKeySize;
 
     // Used to assert that Encryption/Decryption works with same buffer
     // TEXT_LEN is multiple of blocks in order to work against ciphers w/ NoPadding
@@ -68,23 +67,28 @@
     private final byte[] IV;
     private final byte[] INPUT_TEXT;
 
+    // for variable-key-length ciphers
     TestCipher(String algo, String[] modes, String[] paddings,
-            boolean keyStrength) throws NoSuchAlgorithmException {
+            int minKeySize, int maxKeySize) throws NoSuchAlgorithmException {
         ALGORITHM = algo;
         MODES = modes;
         PADDINGS = paddings;
-        this.variousKeySize
-                = keyStrength ? Cipher.getMaxAllowedKeyLength(ALGORITHM) : 0;
-
+        this.minKeySize = minKeySize;
+        int maxAllowedKeySize = Cipher.getMaxAllowedKeyLength(ALGORITHM);
+        if (maxKeySize > maxAllowedKeySize) {
+            maxKeySize = maxAllowedKeySize;
+        }
+        this.maxKeySize = maxKeySize;
         IV = generateBytes(8);
         INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET);
     }
 
+    // for fixed-key-length ciphers
     TestCipher(String algo, String[] modes, String[] paddings) {
         ALGORITHM = algo;
         MODES = modes;
         PADDINGS = paddings;
-        variousKeySize = 0;
+        this.minKeySize = this.maxKeySize = 0;
 
         IV = generateBytes(8);
         INPUT_TEXT = generateBytes(TEXT_LEN + PAD_BYTES + ENC_OFFSET);
@@ -98,8 +102,8 @@
         return bytes;
     }
 
-    private boolean isKeyStrenthSupported() {
-        return (variousKeySize != 0);
+    private boolean isMultipleKeyLengthSupported() {
+        return (maxKeySize != minKeySize);
     }
 
     public void runAll() throws InvalidKeyException,
@@ -110,11 +114,11 @@
 
         for (String mode : MODES) {
             for (String padding : PADDINGS) {
-                if (!isKeyStrenthSupported()) {
-                    runTest(mode, padding, 0);
+                if (!isMultipleKeyLengthSupported()) {
+                    runTest(mode, padding, minKeySize);
                 } else {
-                    int keySize = variousKeySize;
-                    while (keySize >= MINIMUM_KEY_SIZE) {
+                    int keySize = maxKeySize;
+                    while (keySize >= minKeySize) {
                         out.println("With Key Strength: " + keySize);
                         runTest(mode, padding, keySize);
                         keySize -= KEYCUTTER;
@@ -139,6 +143,7 @@
         if (keySize != 0) {
             kg.init(keySize);
         }
+
         SecretKey key = kg.generateKey();
         SecretKeySpec skeySpec = new SecretKeySpec(key.getEncoded(), ALGORITHM);
 
@@ -150,7 +155,6 @@
         }
 
         // Encryption
-
         byte[] plainText = INPUT_TEXT.clone();
 
         // Generate cipher and save to separate buffer
diff --git a/jdk/test/com/sun/jdi/ConstantPoolInfoGC.java b/jdk/test/com/sun/jdi/ConstantPoolInfoGC.java
index 307d9fa..aacf787 100644
--- a/jdk/test/com/sun/jdi/ConstantPoolInfoGC.java
+++ b/jdk/test/com/sun/jdi/ConstantPoolInfoGC.java
@@ -28,7 +28,7 @@
  *
  *  @author Egor Ushakov
  *
- *  @modules jdk.jdi/com.sun.tools.jdi
+ *  @modules jdk.jdi/com.sun.tools.jdi:+open
  *  @run build TestScaffold VMConnection
  *  @run compile -g ConstantPoolInfoGC.java
  *  @run main/othervm ConstantPoolInfoGC
diff --git a/jdk/test/com/sun/jdi/ModulesTest.java b/jdk/test/com/sun/jdi/ModulesTest.java
index e9c8cff..359293f 100644
--- a/jdk/test/com/sun/jdi/ModulesTest.java
+++ b/jdk/test/com/sun/jdi/ModulesTest.java
@@ -78,7 +78,6 @@
         }
         // Sanity checks: make sure there is no crash or exception
         String otherName = other.name();
-        boolean cond = module.canRead(other);
         return true;
     }
 
@@ -159,8 +158,6 @@
             }
             bootUnnamedModule = module;
         }
-        boolean cond = module.canRead(other);
-        println("    can read: " + cond);
     }
 
     // Check that the java.lang.String class was loaded by the java.base module.
@@ -198,24 +195,6 @@
             testFailed = true;
             println(FailPrefix + "unnamed module of PlatformClassLoader was not observed");
         }
-
-        for (ModuleReference module : modules) {
-            if (!bootUnnamedModule.canRead(module)) {
-                testFailed = true;
-                println(FailPrefix + "boot unnamed module must read any module" +
-                        "but a non-readible module is found: " + module.name());
-            }
-            if (!appUnnamedModule.canRead(module)) {
-                testFailed = true;
-                println(FailPrefix + "app unnamed module must read any module" +
-                        "but a non-readible module is found: " + module.name());
-            }
-            if (!extUnnamedModule.canRead(module)) {
-                testFailed = true;
-                println(FailPrefix + "ext unnamed module must read any module" +
-                        "but a non-readible module is found: " + module.name());
-            }
-        }
     }
 
     protected void runTests() throws Exception {
diff --git a/jdk/test/com/sun/jdi/connect/spi/GeneratedConnectors.java b/jdk/test/com/sun/jdi/connect/spi/GeneratedConnectors.java
index b2faba8..dd3dec3 100644
--- a/jdk/test/com/sun/jdi/connect/spi/GeneratedConnectors.java
+++ b/jdk/test/com/sun/jdi/connect/spi/GeneratedConnectors.java
@@ -30,8 +30,8 @@
  * to encapsulate the transport. This tests that the connectors are
  * created and that they have an "address" argument.
  *
- * @modules jdk.jdi
- * @build GeneratedConnectors NullTransportService
+ * @modules jdk.jdi/com.sun.tools.jdi
+ * @build GeneratedConnectors NullTransportService SimpleLaunchingConnector
  * @run main/othervm GeneratedConnectors
  */
 
diff --git a/jdk/test/com/sun/jmx/mbeanserver/introspector/SimpleIntrospectorTest.java b/jdk/test/com/sun/jmx/mbeanserver/introspector/SimpleIntrospectorTest.java
index 3784c93..6a96e9e 100644
--- a/jdk/test/com/sun/jmx/mbeanserver/introspector/SimpleIntrospectorTest.java
+++ b/jdk/test/com/sun/jmx/mbeanserver/introspector/SimpleIntrospectorTest.java
@@ -33,7 +33,7 @@
  *          with a lower-case letter
  *
  * @author Jaroslav Bachorik
- * @modules java.management/com.sun.jmx.mbeanserver
+ * @modules java.management/com.sun.jmx.mbeanserver:open
  * @run clean SimpleIntrospectorTest
  * @run build SimpleIntrospectorTest BeanClass
  * @run main SimpleIntrospectorTest
diff --git a/jdk/test/com/sun/jndi/dns/Parser.java b/jdk/test/com/sun/jndi/dns/Parser.java
index 0484617..58c7bd5 100644
--- a/jdk/test/com/sun/jndi/dns/Parser.java
+++ b/jdk/test/com/sun/jndi/dns/Parser.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8035105
  * @summary DNS resource record parsing
- * @modules jdk.naming.dns/com.sun.jndi.dns
+ * @modules jdk.naming.dns/com.sun.jndi.dns:+open
  * @compile --add-modules jdk.naming.dns Parser.java
  */
 
diff --git a/jdk/test/com/sun/jndi/ldap/SimpleClientIdHashCode.java b/jdk/test/com/sun/jndi/ldap/SimpleClientIdHashCode.java
index 956e2c4..b43440a 100644
--- a/jdk/test/com/sun/jndi/ldap/SimpleClientIdHashCode.java
+++ b/jdk/test/com/sun/jndi/ldap/SimpleClientIdHashCode.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8158802
  * @summary com.sun.jndi.ldap.SimpleClientId produces wrong hash code
- * @modules java.naming/com.sun.jndi.ldap
+ * @modules java.naming/com.sun.jndi.ldap:open
  */
 
 import java.io.OutputStream;
diff --git a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java
index d8590f0..f75eb88 100644
--- a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java
+++ b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,9 @@
  * @modules jdk.naming.rmi/com.sun.jndi.rmi.registry java.rmi/sun.rmi.registry
  *     java.rmi/sun.rmi.server java.rmi/sun.rmi.transport java.rmi/sun.rmi.transport.tcp
  * @library ../../../../../../java/rmi/testlibrary
+ * @build TestLibrary
  * @compile --add-modules jdk.naming.rmi ContextWithNullProperties.java
- * @run main ContextWithNullProperties
+ * @run main/othervm ContextWithNullProperties
  */
 
 import com.sun.jndi.rmi.registry.RegistryContext;
@@ -37,7 +38,7 @@
 
 public class ContextWithNullProperties {
     public static void main(String[] args) throws Exception {
-        Registry registry = TestLibrary.createRegistryOnUnusedPort();
+        Registry registry = TestLibrary.createRegistryOnEphemeralPort();
         int registryPort = TestLibrary.getRegistryPort(registry);
         System.out.println("Connecting to the default Registry...");
         // Connect to the default Registry.
diff --git a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java
index 74f5767..8bcf660 100644
--- a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java
+++ b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java
@@ -31,7 +31,7 @@
  *     jdk.naming.rmi
  * @library ../../../../../../java/rmi/testlibrary
  * @build TestLibrary
- * @run main UnbindIdempotent
+ * @run main/othervm UnbindIdempotent
  */
 
 import java.rmi.registry.Registry;
@@ -43,7 +43,7 @@
 public class UnbindIdempotent {
 
     public static void main(String[] args) throws Exception {
-        Registry registry = TestLibrary.createRegistryOnUnusedPort();
+        Registry registry = TestLibrary.createRegistryOnEphemeralPort();
         int registryPort = TestLibrary.getRegistryPort(registry);
         InitialContext ictx = new InitialContext();
         Context rctx;
diff --git a/jdk/test/com/sun/management/VMOptionOpenDataTest.java b/jdk/test/com/sun/management/VMOptionOpenDataTest.java
index 3436c67..5d25508 100644
--- a/jdk/test/com/sun/management/VMOptionOpenDataTest.java
+++ b/jdk/test/com/sun/management/VMOptionOpenDataTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,58 +21,77 @@
  * questions.
  */
 
+import com.sun.management.HotSpotDiagnosticMXBean;
 import com.sun.management.VMOption;
-import java.io.InvalidObjectException;
-import java.util.Objects;
-import javax.management.openmbean.OpenDataException;
-import sun.management.MappedMXBeanType;
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.management.MBeanServerConnection;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+
+import static javax.management.openmbean.SimpleType.*;
 
 /*
  * @test
  * @bug     8042901
  * @summary Check that MappedMXBeanType.toOpenTypeData supports VMOption
- * @modules java.management/sun.management
- *          jdk.management/com.sun.management
+ * @modules jdk.management/com.sun.management
  * @author  Shanliang Jiang
  */
 public class VMOptionOpenDataTest {
-    public static void main(String[] args) throws Exception {
-        System.out.println("--- VMOptionOpenDataTest-main: Checking that "
-                + "MappedMXBeanType.toOpenTypeData supports VMOption");
-        Exception failed = null;
-        try {
-            VMOption vo = new VMOption("toto", "titi", true, VMOption.Origin.OTHER);
-            System.out.println("--- Construct a VMOption object: \"" + vo + "\"");
+    private static final String[] names = new String[] {
+        "name", "value", "origin", "writeable"
+    };
+    private static final OpenType[] types = new OpenType[] {
+        STRING, STRING, STRING, BOOLEAN
+    };
 
-            Object open = MappedMXBeanType.toOpenTypeData(vo, VMOption.class);
-            System.out.println("--- Map it to an open type:  \"" + open +" \"");
+    public static void main(String... args) throws Exception {
+        MBeanServerConnection msc = ManagementFactory.getPlatformMBeanServer();
+        HotSpotDiagnosticMXBean mxbean =
+            ManagementFactory.getPlatformMXBean(msc, HotSpotDiagnosticMXBean.class);
 
-            Object back = MappedMXBeanType.toJavaTypeData(open, VMOption.class);
-            System.out.println("--- Map it back to java type:  \"" + back +" \"");
 
-            if (back == null) {
-                failed = new RuntimeException("Failed, mapping back got null.");
-            } else if (!(back instanceof VMOption)) {
-                failed = new RuntimeException("Failed, not mapped back to a VMOption: "
-                        +back.getClass());
-            } else {
-                VMOption mapBack = (VMOption)back;
-                if (!Objects.equals(vo.getName(), mapBack.getName()) ||
-                        !Objects.equals(vo.getOrigin(), mapBack.getOrigin()) ||
-                        !Objects.equals(vo.getValue(), mapBack.getValue()) ||
-                        vo.isWriteable() != mapBack.isWriteable()) {
-                    failed = new RuntimeException(
-                            "Failed, failed to map back the original VMOtion.");
-                }
-            }
-        } catch (OpenDataException | InvalidObjectException ode) {
-            failed = ode;
+        String[] signatures = new String[] {
+            String.class.getName()
+        };
+        Object obj = msc.invoke(mxbean.getObjectName(), "getVMOption",
+            new String[] { "PrintVMOptions"}, signatures);
+
+        CompositeData data = (CompositeData)obj;
+        validateType(data);
+
+        VMOption option = mxbean.getVMOption("PrintVMOptions");
+        VMOption o = VMOption.from(data);
+        assertEquals(option, o);
+    }
+
+    private static void validateType(CompositeData data) {
+        CompositeType type = data.getCompositeType();
+        Set<String> keys = Arrays.stream(names).collect(Collectors.toSet());
+        if (!type.keySet().equals(keys)) {
+            throw new RuntimeException("key not matched: " + type.keySet().toString());
         }
-        if (failed == null) {
-            System.out.println("--- PASSED!");
-        } else {
-            System.out.println("--- Failed: "+failed.getMessage());
-            throw failed;
+        for (int i=0; i < names.length; i++) {
+            OpenType t = type.getType(names[i]);
+            if (t != types[i]) {
+                throw new AssertionError(names[i] + ": type not matched: " +
+                    t + " expected: " + types[i]);
+            }
         }
     }
+
+    private static void assertEquals(VMOption o1, VMOption o2) {
+        if (!o1.getName().equals(o2.getName()) ||
+            !o1.getOrigin().equals(o2.getOrigin()) ||
+            !o1.getValue().equals(o2.getValue()) ||
+            o1.isWriteable() != o2.isWriteable()) {
+            throw new AssertionError(o1 + " != " + o2);
+        }
+
+    }
+
 }
diff --git a/jdk/test/com/sun/security/auth/TEST.properties b/jdk/test/com/sun/security/auth/TEST.properties
new file mode 100644
index 0000000..282ca00
--- /dev/null
+++ b/jdk/test/com/sun/security/auth/TEST.properties
@@ -0,0 +1 @@
+modules = jdk.security.auth
diff --git a/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java b/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java
index facbc31..079bc94 100644
--- a/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java
+++ b/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,9 +21,10 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 6710360
+ * @modules jdk.security.jgss
  * @summary export Kerberos session key to applications
  */
 
diff --git a/jdk/test/com/sun/security/sasl/Cram.java b/jdk/test/com/sun/security/sasl/Cram.java
index 6c9251c..1c7fb70 100644
--- a/jdk/test/com/sun/security/sasl/Cram.java
+++ b/jdk/test/com/sun/security/sasl/Cram.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,15 +24,17 @@
 /*
  * @test
  * @bug 4634892
+ * @modules jdk.security.auth
  * @summary Ensure that authentication via CRAM-MD5 works.
  */
 
 /*
  * Can set logging to FINEST to view exchange.
  */
-import javax.security.sasl.*;
-import javax.security.auth.callback.*;
-import java.security.Security;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslServer;
 
 public class Cram {
     private static final String MECH = "CRAM-MD5";
diff --git a/jdk/test/com/sun/security/sasl/TEST.properties b/jdk/test/com/sun/security/sasl/TEST.properties
new file mode 100644
index 0000000..5c3c53e
--- /dev/null
+++ b/jdk/test/com/sun/security/sasl/TEST.properties
@@ -0,0 +1 @@
+modules = java.security.sasl
diff --git a/jdk/test/com/sun/security/sasl/digest/TEST.properties b/jdk/test/com/sun/security/sasl/digest/TEST.properties
new file mode 100644
index 0000000..282ca00
--- /dev/null
+++ b/jdk/test/com/sun/security/sasl/digest/TEST.properties
@@ -0,0 +1 @@
+modules = jdk.security.auth
diff --git a/jdk/test/java/awt/EventDispatchThread/EDTShutdownTest/EDTShutdownTest.java b/jdk/test/java/awt/EventDispatchThread/EDTShutdownTest/EDTShutdownTest.java
index c2d0118..4666c83 100644
--- a/jdk/test/java/awt/EventDispatchThread/EDTShutdownTest/EDTShutdownTest.java
+++ b/jdk/test/java/awt/EventDispatchThread/EDTShutdownTest/EDTShutdownTest.java
@@ -27,6 +27,7 @@
   @summary [macosx] TwentyThousandTest test intermittently hangs
   @author Oleg Pekhovskiy
   @modules java.desktop/sun.awt
+  @modules java.desktop/java.awt:open
   @run main EDTShutdownTest
  */
 
diff --git a/jdk/test/java/awt/Focus/DisposedWindow/DisposeDialogNotActivateOwnerTest/DisposeDialogNotActivateOwnerTest.html b/jdk/test/java/awt/Focus/DisposedWindow/DisposeDialogNotActivateOwnerTest/DisposeDialogNotActivateOwnerTest.html
deleted file mode 100644
index 28ae8df..0000000
--- a/jdk/test/java/awt/Focus/DisposedWindow/DisposeDialogNotActivateOwnerTest/DisposeDialogNotActivateOwnerTest.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6386592
-  @summary    Tests that disposing a dialog doesn't activate its invisible owner.
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @run        applet DisposeDialogNotActivateOwnerTest.html
-  -->
-<head>
-<title>DisposeDialogNotActivateOwnerTest</title>
-</head>
-<body>
- 
-<h1>DisposeDialogNotActivateOwnerTest<br>Bug ID: 6386592</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=DisposeDialogNotActivateOwnerTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
diff --git a/jdk/test/java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent1.java b/jdk/test/java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent1.java
index a6730e0..4c03da8 100644
--- a/jdk/test/java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent1.java
+++ b/jdk/test/java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent1.java
@@ -29,6 +29,7 @@
   @library ../../regtesthelpers
   @modules java.desktop/java.awt.peer
            java.desktop/sun.awt
+           java.desktop/java.awt:open
   @build Util
   @run main RequestOnCompWithNullParent1
 */
diff --git a/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
index 25b96af..7240f441 100644
--- a/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
+++ b/jdk/test/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
@@ -30,7 +30,7 @@
   @requires (os.family == "linux" | os.family == "solaris")
   @modules java.desktop/sun.awt
            java.desktop/java.awt.peer
-           java.desktop/sun.awt.X11
+           java.desktop/sun.awt.X11:open
   @run applet FocusEmptyListTest.html
   -->
 <head>
diff --git a/jdk/test/java/awt/Modal/LWModalTest/LWModalTest.java b/jdk/test/java/awt/Modal/LWModalTest/LWModalTest.java
index dd7829b..de14ff7 100644
--- a/jdk/test/java/awt/Modal/LWModalTest/LWModalTest.java
+++ b/jdk/test/java/awt/Modal/LWModalTest/LWModalTest.java
@@ -28,6 +28,7 @@
   @summary The test checks that Container's method startLWModal
 and stopLWModal work correctly. The test scenario is very close
 to JOptionPane.showInternal*Dialog methods
+  @modules java.desktop/java.awt:open
   @author artem.ananiev@...: area=awt.modal
   @library ../../regtesthelpers
   @build Util
diff --git a/jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java b/jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java
index 32217e8..1ef644b 100644
--- a/jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java
+++ b/jdk/test/java/awt/TextArea/TextAreaCaretVisibilityTest/bug7129742.java
@@ -34,7 +34,7 @@
  * @requires (os.family == "linux" | os.family == "solaris")
  * @modules java.desktop/sun.awt
  *          java.desktop/java.awt.peer
- *          java.desktop/sun.awt.X11
+ *          java.desktop/sun.awt.X11:open
  * @author Sean Chou
  */
 
diff --git a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
index 1683ba9..714d100 100644
--- a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
+++ b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh
@@ -154,16 +154,16 @@
 case "$OS" in
   Windows* | CYGWIN* )
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
-                         --add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
+                         --add-opens java.desktop/sun.awt=ALL-UNNAMED \
+                         --add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
                          TestWrapped sun.awt.windows.WToolkit
     status=$?
     if [ ! $status -eq "0" ]; then
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.windows.WToolkit";
     fi
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
-                         --add-exports java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
+                         --add-opens java.desktop/sun.awt=ALL-UNNAMED \
+                         --add-opens java.desktop/sun.awt.windows=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.awt.windows.WToolkit \
                          TestWrapped sun.awt.windows.WToolkit
     status=$?
@@ -174,8 +174,8 @@
 
   SunOS | Linux )
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
-                         --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
+                         --add-opens java.desktop/sun.awt=ALL-UNNAMED \
+                         --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.awt.X11.XToolkit \
                          TestWrapped sun.awt.X11.XToolkit
     status=$?
@@ -183,8 +183,8 @@
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.awt.xawt.XToolkit";
     fi
     AWT_TOOLKIT=XToolkit ${TESTJAVA}/bin/java ${TESTVMOPTS} \
-                         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
-                         --add-exports java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
+                         --add-opens java.desktop/sun.awt=ALL-UNNAMED \
+                         --add-opens java.desktop/sun.awt.X11=ALL-UNNAMED ${CP} \
                                               -Djava.awt.headless=true \
                                               TestWrapped sun.awt.X11.XToolkit
     status=$?
@@ -195,16 +195,16 @@
 
   Darwin)
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
-                         --add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
+                         --add-opens java.desktop/sun.awt=ALL-UNNAMED \
+                         --add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
                          TestWrapped sun.lwawt.macosx.LWCToolkit
     status=$?
     if [ ! $status -eq "0" ]; then
       fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
     fi
     ${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.awt.headless=true \
-                         --add-exports java.desktop/sun.awt=ALL-UNNAMED \
-                         --add-exports java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
+                         --add-opens java.desktop/sun.awt=ALL-UNNAMED \
+                         --add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED ${CP} \
                          -Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \
                          TestWrapped sun.lwawt.macosx.LWCToolkit
     status=$?
diff --git a/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java b/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java
index 25254d5..bf79e98 100644
--- a/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java
+++ b/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java
@@ -30,6 +30,7 @@
  *          of the ActionEvent triggered when TrayIcon is double clicked
  *          (single clicked, on Mac)
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library ../../../../lib/testlibrary ../
  * @library /java/awt/patchlib
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java b/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java
index e8710ed..77afc31 100644
--- a/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java
+++ b/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java
@@ -33,6 +33,7 @@
  *          triggered when multiple AWTEventListeners and ActionListeners
  *          are added.
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java
index 95879ce..56f0785 100644
--- a/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java
+++ b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java
@@ -25,6 +25,8 @@
  * @test
  * @bug 6191390 8154328
  * @summary Verify that ActionEvent is received with correct modifiers set.
+ * @modules java.desktop/java.awt:open
+ * @modules java.desktop/java.awt.peer
  * @library ../../../../lib/testlibrary ../
  * @library /java/awt/patchlib
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java b/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java
index dca4ef0..9413915 100644
--- a/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java
+++ b/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java
@@ -29,6 +29,7 @@
  * @test
  * @summary Check for MouseEvents with all mouse buttons
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build ExtendedRobot SystemTrayIconHelper
diff --git a/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java b/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java
index c530d28..7996c4f 100644
--- a/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java
+++ b/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java
@@ -32,6 +32,7 @@
  *          checks if all listeners are triggered when AWTEventListeners
  *          and MouseListeners are added.
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java b/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java
index 4f8b91c..5e71ac7 100644
--- a/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java
+++ b/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java
@@ -29,6 +29,7 @@
  * @test
  * @summary Check for MouseEvents with all mouse buttons
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../../lib/testlibrary ../../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java
index 453b467..bca5af9 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java
@@ -39,6 +39,7 @@
  * @key headful
  * @summary Check if MouseEvent has the proper modifiers when
  *          TrayIcon is clicked pressing the modifier keys
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java b/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java
index 72a8fe5..c1e60d4 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java
@@ -30,6 +30,7 @@
  * @test
  * @summary Check for MouseEvents with all mouse buttons
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java b/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
index f7549a3..3d6d224f 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java
@@ -34,6 +34,7 @@
  *          it is double clicked with mouse button 1 on windows
  *          or single clicked with button 3 on Mac OS X
  *          or single clicked with button 1 on rest.
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
index f59ff63..f09219c 100644
--- a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
+++ b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java
@@ -29,6 +29,7 @@
  * @summary Check if a JPopupMenu can be displayed when TrayIcon is
  *          right clicked. It uses a JWindow as the parent of the JPopupMenu
  * @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
+ * @modules java.desktop/java.awt:open
  * @library /java/awt/patchlib
  * @library ../../../../lib/testlibrary ../
  * @build java.desktop/java.awt.Helper
diff --git a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java
index 81fdd4b..588f6b6 100644
--- a/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java
+++ b/jdk/test/java/awt/Window/OwnedWindowsLeak/OwnedWindowsLeak.java
@@ -26,6 +26,7 @@
   @key headful
   @bug 6758673
   @summary Tests that windows are removed from owner's child windows list
+  @modules java.desktop/java.awt:open
   @author art: area=awt.toplevel
   @run main/othervm -mx128m OwnedWindowsLeak
 */
diff --git a/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java b/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java
index 25884f9..384a4ea 100644
--- a/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java
+++ b/jdk/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java
@@ -27,6 +27,7 @@
   @bug 6315717
   @summary verifies that InputEvents button masks arrays are the same
   @author Andrei Dmitriev : area=awt.event
+  @modules java.desktop/java.awt.event:open
   @run main ButtonArraysEquality
  */
 
diff --git a/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java b/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java
index 879aee5..8770a72 100644
--- a/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java
+++ b/jdk/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java
@@ -25,6 +25,7 @@
   @test %I% %E%
   @key headful
   @bug 6315717
+  @modules java.desktop/java.awt.event:open
   @summary verifies that InputEvent.getMaskForButton() returns the same values as in InputEvent.BUTTON_DOWN_MASK
   @author Andrei Dmitriev : area=awt.event
   @run main CheckGetMaskForButton
diff --git a/jdk/test/java/awt/font/FontNames/GetLCIDFromLocale.java b/jdk/test/java/awt/font/FontNames/GetLCIDFromLocale.java
index ef220b9..8c49d44 100644
--- a/jdk/test/java/awt/font/FontNames/GetLCIDFromLocale.java
+++ b/jdk/test/java/awt/font/FontNames/GetLCIDFromLocale.java
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 4351212
- * @modules java.desktop/sun.font
+ * @modules java.desktop/sun.font:open
  * @summary Verify that new getLCIDFromLocale method works
  */
 
diff --git a/jdk/test/java/awt/image/MultiResolutionImageTest.java b/jdk/test/java/awt/image/MultiResolutionImageTest.java
index a1f70e5..a1e85c9 100644
--- a/jdk/test/java/awt/image/MultiResolutionImageTest.java
+++ b/jdk/test/java/awt/image/MultiResolutionImageTest.java
@@ -48,7 +48,7 @@
  * @requires (os.family == "mac")
  * @modules java.desktop/sun.awt
  *          java.desktop/sun.awt.image
- *          java.desktop/sun.lwawt.macosx
+ *          java.desktop/sun.lwawt.macosx:open
  * @run main MultiResolutionImageTest TOOLKIT_PREPARE
  * @run main MultiResolutionImageTest TOOLKIT_LOAD
  * @run main MultiResolutionImageTest TOOLKIT
diff --git a/jdk/test/java/awt/patchlib/java.desktop/java/awt/Helper.java b/jdk/test/java/awt/patchlib/java.desktop/java/awt/Helper.java
index c16e580..6d8dbc4 100644
--- a/jdk/test/java/awt/patchlib/java.desktop/java/awt/Helper.java
+++ b/jdk/test/java/awt/patchlib/java.desktop/java/awt/Helper.java
@@ -26,6 +26,6 @@
 public class Helper {
     private Helper() { }
     public static void addExports(String pn, Module target) {
-        java.awt.Component.class.getModule().addExports(pn, target);
+        java.awt.Component.class.getModule().addOpens(pn, target);
     }
 }
diff --git a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java
index 883e6d0..2739f45 100644
--- a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java
+++ b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 6380849
  * @summary Tests BeanInfo finder
+ * @modules java.desktop/java.beans:open
  * @author Sergey Malenkov
  */
 
diff --git a/jdk/test/java/beans/XMLEncoder/java_awt_CardLayout.java b/jdk/test/java/beans/XMLEncoder/java_awt_CardLayout.java
index aa6a3fc..382bba5 100644
--- a/jdk/test/java/beans/XMLEncoder/java_awt_CardLayout.java
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_CardLayout.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8007458
  * @summary Tests CardLayout encoding
+ * @modules java.desktop/java.awt:open
  * @author Sergey Malenkov
  */
 
diff --git a/jdk/test/java/beans/XMLEncoder/java_awt_GridBagLayout.java b/jdk/test/java/beans/XMLEncoder/java_awt_GridBagLayout.java
index 7011dbd..12af820 100644
--- a/jdk/test/java/beans/XMLEncoder/java_awt_GridBagLayout.java
+++ b/jdk/test/java/beans/XMLEncoder/java_awt_GridBagLayout.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8007458
  * @summary Tests GridBagLayout encoding
+ * @modules java.desktop/java.awt:open
  * @author Sergey Malenkov
  */
 
diff --git a/jdk/test/java/io/FilePermission/Correctness.java b/jdk/test/java/io/FilePermission/Correctness.java
index 7911dd6..140aa8b 100644
--- a/jdk/test/java/io/FilePermission/Correctness.java
+++ b/jdk/test/java/io/FilePermission/Correctness.java
@@ -25,6 +25,7 @@
  *
  * @test
  * @bug 8164705
+ * @modules java.base/java.io:open
  * @summary Remove pathname canonicalization from FilePermission
  */
 
diff --git a/jdk/test/java/io/FilePermission/MergeName.java b/jdk/test/java/io/FilePermission/MergeName.java
new file mode 100644
index 0000000..0921587
--- /dev/null
+++ b/jdk/test/java/io/FilePermission/MergeName.java
@@ -0,0 +1,84 @@
+/*
+ * 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 jdk.test.lib.process.ProcessTools;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * @test
+ * @bug 8170364
+ * @summary FilePermission path modified during merge
+ * @library /test/lib
+ */
+
+public class MergeName {
+
+    public static final String[] ALL_ACTIONS
+            = {"read", "write", "execute", "delete"};
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            test("p1", "read", "write", "delete", "execute");
+            test("p2", "read,write", "delete,execute");
+            test("p3", "read,write,delete", "execute");
+            test("p4", "read,write,delete,execute");
+        } else {
+            SecurityManager sm = System.getSecurityManager();
+            for (String arg : args) {
+                // Use bits to create powerset of ALL_ACTIONS
+                IntStream.range(1, 16)
+                        .mapToObj(n -> IntStream.range(0, 4)
+                                .filter(x -> (n & (1 << x)) != 0)
+                                .mapToObj(x -> ALL_ACTIONS[x])
+                                .collect(Collectors.joining(",")))
+                        .forEach(a -> sm.checkPermission(
+                                new FilePermission(arg, a)));
+            }
+        }
+    }
+
+    private static void test(String file, String... actions) throws Exception {
+        List<String> content = new ArrayList<>();
+        content.add("grant {");
+        for (String action : actions) {
+            content.add("   permission java.io.FilePermission " +
+                    "\"x\", \"" +action + "\";");
+        }
+        content.add("};");
+        Files.write(Paths.get(file), content);
+        ProcessTools.executeTestJvm("-Djava.security.manager",
+                "-Djava.security.policy=" + file,
+                "MergeName",
+                "x",
+                new File(System.getProperty("user.dir"), "x").getPath())
+            .shouldHaveExitValue(0);
+    }
+}
diff --git a/jdk/test/java/io/ObjectInputStream/PeekInputStreamTest.java b/jdk/test/java/io/ObjectInputStream/PeekInputStreamTest.java
index 86e8001..b388066 100644
--- a/jdk/test/java/io/ObjectInputStream/PeekInputStreamTest.java
+++ b/jdk/test/java/io/ObjectInputStream/PeekInputStreamTest.java
@@ -30,6 +30,7 @@
 /*
  * @test
  * @bug 8067870
+ * @modules java.base/java.io:open
  * @summary verifies java.io.ObjectInputStream.PeekInputStream.skip works
  *          as intended
  */
diff --git a/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java b/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java
index 0a4905d..9a7811e 100644
--- a/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java
+++ b/jdk/test/java/lang/Character/UnicodeBlock/OptimalMapSize.java
@@ -26,6 +26,8 @@
  * @bug 8080535
  * @summary Expected size of Character.UnicodeBlock.map is not optimal
  * @library /lib/testlibrary
+ * @modules java.base/java.lang:open
+ *          java.base/java.util:open
  * @build jdk.testlibrary.OptimalCapacity
  * @run main OptimalMapSize
  */
diff --git a/jdk/test/java/lang/Class/GetModuleTest.java b/jdk/test/java/lang/Class/GetModuleTest.java
index 3feb998..f0d7477 100644
--- a/jdk/test/java/lang/Class/GetModuleTest.java
+++ b/jdk/test/java/lang/Class/GetModuleTest.java
@@ -31,7 +31,6 @@
  */
 
 import java.awt.Component;
-import java.lang.reflect.Field;
 import java.lang.reflect.Module;
 
 import jdk.internal.org.objectweb.asm.ClassWriter;
@@ -44,16 +43,7 @@
 
 public class GetModuleTest {
 
-    static final Unsafe U;
-    static {
-        try {
-            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafe.setAccessible(true);
-            U = (Unsafe) theUnsafe.get(null);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
+    private static final Unsafe U = Unsafe.getUnsafe();
 
     private static final Module TEST_MODULE = GetModuleTest.class.getModule();
 
diff --git a/jdk/test/java/lang/Class/forName/modules/src/m2/p2/test/Main.java b/jdk/test/java/lang/Class/forName/modules/src/m2/p2/test/Main.java
index 83856c6..56cec62 100644
--- a/jdk/test/java/lang/Class/forName/modules/src/m2/p2/test/Main.java
+++ b/jdk/test/java/lang/Class/forName/modules/src/m2/p2/test/Main.java
@@ -44,7 +44,7 @@
         try {
             Class<?> c = findClass(m1, "p1.internal.B");
             c.newInstance();
-            throw new RuntimeException(c.getName() + " is not exported to m2");
+            throw new RuntimeException(c.getName() + " should not be exported to m2");
         } catch (IllegalAccessException e) {}
     }
 
diff --git a/jdk/test/java/lang/Class/getDeclaredField/ClassDeclaredFieldsTest.java b/jdk/test/java/lang/Class/getDeclaredField/ClassDeclaredFieldsTest.java
index 2441a17..0c53acc 100644
--- a/jdk/test/java/lang/Class/getDeclaredField/ClassDeclaredFieldsTest.java
+++ b/jdk/test/java/lang/Class/getDeclaredField/ClassDeclaredFieldsTest.java
@@ -40,6 +40,7 @@
  *          set accessible if the right permission is granted; this test
  *          also verifies that Class.classLoader final private field is
  *          hidden from reflection access.
+ * @modules java.base/java.lang:open
  * @run main/othervm ClassDeclaredFieldsTest UNSECURE
  * @run main/othervm ClassDeclaredFieldsTest SECURE
  *
diff --git a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
index 5f4dcea..90a34a5 100644
--- a/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
+++ b/jdk/test/java/lang/Class/getDeclaredField/FieldSetAccessibleTest.java
@@ -58,9 +58,9 @@
 /**
  * @test
  * @bug 8065552
- * @summary test that all fields returned by getDeclaredFields() can be
- *          set accessible if the right permission is granted; this test
- *          loads all the classes in the BCL, get their declared fields,
+ * @summary test that all public fields returned by getDeclaredFields() can
+ *          be set accessible if the right permission is granted; this test
+ *          loads all classes and get their declared fields
  *          and call setAccessible(false) followed by setAccessible(true);
  * @modules java.base/jdk.internal.module
  * @run main/othervm --add-modules=ALL-SYSTEM FieldSetAccessibleTest UNSECURE
@@ -81,24 +81,30 @@
 
 
     // Test that all fields for any given class can be made accessibles
-    static void testSetFieldsAccessible(Class<?> c, boolean expectException) {
+    static void testSetFieldsAccessible(Class<?> c) {
+        Module self = FieldSetAccessibleTest.class.getModule();
+        Module target = c.getModule();
+        String pn = c.getPackageName();
+        boolean exported = self.canRead(target) && target.isExported(pn, self);
         for (Field f : c.getDeclaredFields()) {
             fieldCount.incrementAndGet();
-            boolean expect = expectException;
-            if ((c == Module.class || c == AccessibleObject.class) &&
-                !Modifier.isPublic(f.getModifiers())) {
-                expect = true;
-            }
+
+            // setAccessible succeeds only if it's exported and the member
+            // is public and of a public class, or it's opened
+            // otherwise it would fail.
+            boolean isPublic = Modifier.isPublic(f.getModifiers()) &&
+                Modifier.isPublic(c.getModifiers());
+            boolean access = (exported && isPublic) || target.isOpen(pn, self);
             try {
                 f.setAccessible(false);
                 f.setAccessible(true);
-                if (expect) {
+                if (!access) {
                     throw new RuntimeException(
                         String.format("Expected InaccessibleObjectException is not thrown "
                                       + "for field %s in class %s%n", f.getName(), c.getName()));
                 }
             } catch (InaccessibleObjectException expected) {
-                if (!expect) {
+                if (access) {
                     throw new RuntimeException(expected);
                 }
             }
@@ -110,18 +116,17 @@
     public static boolean test(Class<?> c, boolean addExports) {
         Module self = FieldSetAccessibleTest.class.getModule();
         Module target = c.getModule();
-        String pn = c.getPackage().getName();
+        String pn = c.getPackageName();
         boolean exported = self.canRead(target) && target.isExported(pn, self);
         if (addExports && !exported) {
             Modules.addExports(target, pn, self);
             exported = true;
         }
-        boolean expectException = !exported;
 
         classCount.incrementAndGet();
 
         // Call getDeclaredFields() and try to set their accessible flag.
-        testSetFieldsAccessible(c, expectException);
+        testSetFieldsAccessible(c);
 
         // add more tests here...
 
diff --git a/jdk/test/java/lang/Class/getResource/Main.java b/jdk/test/java/lang/Class/getResource/Main.java
index b1b45f3..96d4e68 100644
--- a/jdk/test/java/lang/Class/getResource/Main.java
+++ b/jdk/test/java/lang/Class/getResource/Main.java
@@ -24,7 +24,6 @@
 import java.lang.module.Configuration;
 import java.lang.module.ResolvedModule;
 import java.lang.reflect.Layer;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -33,8 +32,8 @@
 import java.nio.file.Paths;
 
 /**
- * Basic test of Class getResource and getResourceAsStream when invoked from
- * code in named modules.
+ * Basic test of Class getResource and getResourceAsStream to locate/read
+ * resources in named modules.
  */
 
 public class Main {
@@ -43,62 +42,192 @@
 
     public static void main(String[] args) throws IOException {
 
-        // create m1/myresource containing "m1"
-        Path file = directoryFor("m1").resolve(NAME);
-        Files.write(file, "m1".getBytes("UTF-8"));
+        // create resources in m1
+        createResource("m1", Paths.get("."), "m1");
+        createResource("m1", Paths.get("p1"), "m1/p1");
+        createResource("m1", Paths.get("p1", "impl"), "m1/p1.impl");
+        createResource("m1", Paths.get("p1", "resources"), "m1/p1.resources");
 
-        // create m2/myresource containing "m2"
-        file = directoryFor("m2").resolve(NAME);
-        Files.write(file, "m2".getBytes("UTF-8"));
+        // create resources in m2
+        createResource("m2", Paths.get("."), "m2");
+        createResource("m2", Paths.get("p2"), "m2/p2");
+        createResource("m2", Paths.get("p2", "impl"), "m2/p2.impl");
+        createResource("m2", Paths.get("p2", "resources"), "m2/p2.resources");
 
-        // check that m3/myresource does not exist
-        assertTrue(Files.notExists(directoryFor("m3").resolve(NAME)));
 
-        // invoke Class getResource from the unnamed module
-        URL url0 = Main.class.getResource("/" + NAME);
-        assertNull(url0);
+        // invoke Class getResource from an unnamed module.
+        URL url = Main.class.getResource("/" + NAME);
+        assertNotNull(url);
 
-        // invoke Class getResource from modules m1-m3
-        URL url1 = p1.Main.getResource("/" + NAME);
-        URL url2 = p2.Main.getResource("/" + NAME);
-        URL url3 = p3.Main.getResource("/" + NAME);
-        assertNotNull(url1);
-        assertNotNull(url2);
-        assertNull(url3);
+        url = Main.class.getResource("/p1/" + NAME);
+        assertNull(url);
 
-        // check contents of resurces at url1 and url2
-        assertEquals(new String(readAll(url1), "UTF-8"), "m1");
-        assertEquals(new String(readAll(url2), "UTF-8"), "m2");
+        url = Main.class.getResource("/p1/impl/" + NAME);
+        assertNull(url);
 
-        // invoke Class getResourceAsStream from the unnamed module
-        InputStream in0 = Main.class.getResourceAsStream("/" + NAME);
-        assertNull(in0);
+        url = Main.class.getResource("/p1/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.resources");
 
-        // invoke Class getResourceAsStream from modules m1-m3
-        try (InputStream in = p1.Main.getResourceAsStream("/" + NAME)) {
-            String s = new String(in.readAllBytes(), "UTF-8");
-            assertEquals(s, "m1");
-        }
-        try (InputStream in = p2.Main.getResourceAsStream("/" + NAME)) {
-            String s = new String(in.readAllBytes(), "UTF-8");
-            assertEquals(s, "m2");
-        }
-        InputStream in3 = p3.Main.getResourceAsStream("/" + NAME);
-        assertNull(in3);
+        url = Main.class.getResource("/p2/" + NAME);
+        assertNull(url);
 
-        // invoke Module getResources on modules m1-m3
-        InputStream in1 = p1.Main.class.getModule().getResourceAsStream("/" + NAME);
-        InputStream in2 = p2.Main.class.getModule().getResourceAsStream("/" + NAME);
-        in3 = p3.Main.class.getModule().getResourceAsStream("/" + NAME);
-        assertNotNull(in1);
-        assertNotNull(in2);
-        assertNull(in3);
+        url = Main.class.getResource("/p2/impl/" + NAME);
+        assertNull(url);
 
-        // check the content of in1 and in2
-        String s1 = new String(in1.readAllBytes(), "UTF-8");
-        String s2 = new String(in2.readAllBytes(), "UTF-8");
-        assertEquals(s1, "m1");
-        assertEquals(s2, "m2");
+        // m1: exports private p1.resources
+        url = Main.class.getResource("/p2/resources/" + NAME);
+        assertNull(url);
+
+
+        // invoke Class getResource from module m1
+        url = p1.Main.getResource("/" + NAME);
+        assertEquals(readAllAsString(url), "m1");
+
+        url = p1.Main.getResource("/p1/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1");
+
+        url = p1.Main.getResource("/p1/impl/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.impl");
+
+        url = p1.Main.getResource("/p1/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.resources");
+
+        // m2: not a named package
+        url = p1.Main.getResource(p2.Main.class, "/" + NAME);
+        assertEquals(readAllAsString(url), "m2");
+
+        url = p1.Main.getResource(p2.Main.class, "/p2/" + NAME);
+        assertNull(url);
+
+        // m2: exports p2.impl to m1
+        url = p1.Main.getResource(p2.Main.class, "/p2/impl/" + NAME);
+        assertNull(url);
+
+        // m2: exports private p2.resources to m1;
+        url = p1.Main.getResource(p2.Main.class, "/p2/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m2/p2.resources");
+
+
+        // invoke Class getResource from module m2
+        url = p2.Main.getResource("/" + NAME);
+        assertEquals(readAllAsString(url), "m2");
+
+        url = p2.Main.getResource("/p2/" + NAME);
+        assertEquals(readAllAsString(url), "m2/p2");
+
+        url = p2.Main.getResource("/p2/impl/" + NAME);
+        assertEquals(readAllAsString(url), "m2/p2.impl");
+
+        url = p2.Main.getResource("/p2/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m2/p2.resources");
+
+        // m1: not a named package
+        url = p2.Main.getResource(p1.Main.class, "/" + NAME);
+        assertEquals(readAllAsString(url), "m1");
+
+        url = p2.Main.getResource(p1.Main.class, "/p1/" + NAME);
+        assertNull(url);
+
+        url = p2.Main.getResource(p1.Main.class, "/p1/impl/" + NAME);
+        assertNull(url);
+
+        // m1: exports private p1.resources;
+        url = p2.Main.getResource(p1.Main.class, "/p1/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.resources");
+
+
+        // invoke Class getResourceAsStream from an unnamed module.
+        InputStream in = Main.class.getResourceAsStream("/" + NAME);
+        assertNotNull(in);
+
+        in = Main.class.getResourceAsStream("/p1/" + NAME);
+        assertNull(in);
+
+        in = Main.class.getResourceAsStream("/p1/impl/" + NAME);
+        assertNull(in);
+
+        in = Main.class.getResourceAsStream("/p1/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.resources");
+
+        in = Main.class.getResourceAsStream("/p2/" + NAME);
+        assertNull(in);
+
+        in = Main.class.getResourceAsStream("/p2/impl/" + NAME);
+        assertNull(in);
+
+        in = Main.class.getResourceAsStream("/p2/resources/" + NAME);
+        assertNull(in);
+
+
+        // invoke Class getResourceAsStream from module m1
+        in = p1.Main.getResourceAsStream("/" + NAME);
+        assertEquals(readAllAsString(in), "m1");
+
+        in = p1.Main.getResourceAsStream("/p1/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1");
+
+        in = p1.Main.getResourceAsStream("/p1/impl/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.impl");
+
+        in = p1.Main.getResourceAsStream("/p1/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.resources");
+
+        in = p1.Main.getResourceAsStream(p2.Main.class, "/" + NAME);
+        assertEquals(readAllAsString(in), "m2");
+
+        in = p1.Main.getResourceAsStream(p2.Main.class, "/p2/" + NAME);
+        assertNull(in);
+
+        in = p1.Main.getResourceAsStream(p2.Main.class, "/p2/impl/" + NAME);
+        assertNull(in);
+
+        in = p1.Main.getResourceAsStream(p2.Main.class, "/p2/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m2/p2.resources");
+
+
+        // invoke Class getResourceAsStream from module m2
+        in = p2.Main.getResourceAsStream("/" + NAME);
+        assertEquals(readAllAsString(in), "m2");
+
+        in = p2.Main.getResourceAsStream("/p2/" + NAME);
+        assertEquals(readAllAsString(in), "m2/p2");
+
+        in = p2.Main.getResourceAsStream("/p2/impl/" + NAME);
+        assertEquals(readAllAsString(in), "m2/p2.impl");
+
+        in = p2.Main.getResourceAsStream("/p2/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m2/p2.resources");
+
+        in = p2.Main.getResourceAsStream(p1.Main.class, "/" + NAME);
+        assertEquals(readAllAsString(in), "m1");
+
+        in = p2.Main.getResourceAsStream(p1.Main.class, "/p1/" + NAME);
+        assertNull(in);
+
+        in = p2.Main.getResourceAsStream(p1.Main.class, "/p1/impl/" + NAME);
+        assertNull(in);
+
+        in = p2.Main.getResourceAsStream(p1.Main.class, "/p1/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.resources");
+
+
+        // Nulls
+        try {
+            Main.class.getResource(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+        try {
+            Main.class.getResourceAsStream(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+        try {
+            p1.Main.class.getResource(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+        try {
+            p1.Main.class.getResourceAsStream(null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
 
         // SecurityManager case
         System.setSecurityManager(new SecurityManager());
@@ -106,17 +235,24 @@
         assertNull(Main.class.getResource("/" + NAME));
         assertNull(p1.Main.getResource("/" + NAME));
         assertNull(p2.Main.getResource("/" + NAME));
-        assertNull(p3.Main.getResource("/" + NAME));
 
         assertNull(Main.class.getResourceAsStream("/" + NAME));
         assertNull(p1.Main.getResourceAsStream("/" + NAME));
         assertNull(p2.Main.getResourceAsStream("/" + NAME));
-        assertNull(p3.Main.getResourceAsStream("/" + NAME));
 
         System.out.println("Success!");
     }
 
     /**
+     * Create a resource in the sub-directory of the given exploded module
+     */
+    static void createResource(String mn, Path subdir, String msg) throws IOException {
+        Path dir = directoryFor(mn).resolve(subdir);
+        Path file = dir.resolve(NAME);
+        Files.write(file, msg.getBytes("UTF-8"));
+    }
+
+    /**
      * Returns the directory for the given module (by name).
      */
     static Path directoryFor(String name) {
@@ -130,12 +266,21 @@
         return dir;
     }
 
-    static byte[] readAll(URL url) throws IOException {
-        try (InputStream in = url.openStream()) {
-            return in.readAllBytes();
+    static String readAllAsString(InputStream in) throws IOException {
+        if (in == null)
+            return null;
+        try (in) {
+            return new String(in.readAllBytes(), "UTF-8");
         }
     }
 
+    static String readAllAsString(URL url) throws IOException {
+        if (url == null)
+            return null;
+        InputStream in = url.openStream();
+        return readAllAsString(url.openStream());
+    }
+
     static void assertTrue(boolean condition) {
         if (!condition) throw new RuntimeException();
     }
diff --git a/jdk/test/java/lang/Class/getResource/ResourcesTest.java b/jdk/test/java/lang/Class/getResource/ResourcesTest.java
index 97fdae6..7d15576 100644
--- a/jdk/test/java/lang/Class/getResource/ResourcesTest.java
+++ b/jdk/test/java/lang/Class/getResource/ResourcesTest.java
@@ -68,7 +68,7 @@
             .compile(Paths.get(TEST_SRC, "Main.java"),
                      CLASSES_DIR,
                      "--module-path", MODS_DIR.toString(),
-                     "--add-modules", "m1,m2,m3");
+                     "--add-modules", "m1,m2");
         assertTrue(compiled);
 
     }
@@ -80,7 +80,7 @@
 
         int exitValue
             = executeTestJava("--module-path", MODS_DIR.toString(),
-                              "--add-modules", "m1,m2,m3",
+                              "--add-modules", "m1,m2",
                                "-cp", CLASSES_DIR.toString(),
                               "Main")
                 .outputTo(System.out)
diff --git a/jdk/test/java/lang/Class/getResource/src/m1/module-info.java b/jdk/test/java/lang/Class/getResource/src/m1/module-info.java
index 47a2c4c..e29065e 100644
--- a/jdk/test/java/lang/Class/getResource/src/m1/module-info.java
+++ b/jdk/test/java/lang/Class/getResource/src/m1/module-info.java
@@ -23,4 +23,5 @@
 
 module m1 {
     exports p1;
+    opens p1.resources;
 }
diff --git a/jdk/test/java/lang/Class/getResource/src/m1/p1/Main.java b/jdk/test/java/lang/Class/getResource/src/m1/p1/Main.java
index afc1395..370c294 100644
--- a/jdk/test/java/lang/Class/getResource/src/m1/p1/Main.java
+++ b/jdk/test/java/lang/Class/getResource/src/m1/p1/Main.java
@@ -36,4 +36,12 @@
     public static InputStream getResourceAsStream(String name) {
         return Main.class.getResourceAsStream(name);
     }
+
+    public static URL getResource(Class<?> c, String name) {
+        return c.getResource(name);
+    }
+
+    public static InputStream getResourceAsStream(Class<?> c, String name) {
+        return c.getResourceAsStream(name);
+    }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/Class/getResource/src/m1/p1/impl/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/Class/getResource/src/m1/p1/impl/Type.java
index 9d2c8be..12820db 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/Class/getResource/src/m1/p1/impl/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p1.impl;
+
+public class Type { }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/Class/getResource/src/m1/p1/resources/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/Class/getResource/src/m1/p1/resources/Type.java
index 9d2c8be..6dcc132 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/Class/getResource/src/m1/p1/resources/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p1.resources;
+
+public class Type { }
diff --git a/jdk/test/java/lang/Class/getResource/src/m2/module-info.java b/jdk/test/java/lang/Class/getResource/src/m2/module-info.java
index e28b220..6b7c3ef 100644
--- a/jdk/test/java/lang/Class/getResource/src/m2/module-info.java
+++ b/jdk/test/java/lang/Class/getResource/src/m2/module-info.java
@@ -23,4 +23,6 @@
 
 module m2 {
     exports p2;
+    exports p2.impl to m1;
+    opens p2.resources to m1;
 }
diff --git a/jdk/test/java/lang/Class/getResource/src/m2/p2/Main.java b/jdk/test/java/lang/Class/getResource/src/m2/p2/Main.java
index 51bdcf6..f24e5fd 100644
--- a/jdk/test/java/lang/Class/getResource/src/m2/p2/Main.java
+++ b/jdk/test/java/lang/Class/getResource/src/m2/p2/Main.java
@@ -36,4 +36,12 @@
     public static InputStream getResourceAsStream(String name) {
         return Main.class.getResourceAsStream(name);
     }
+
+    public static URL getResource(Class<?> c, String name) {
+        return c.getResource(name);
+    }
+
+    public static InputStream getResourceAsStream(Class<?> c, String name) {
+        return c.getResourceAsStream(name);
+    }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/Class/getResource/src/m2/p2/impl/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/Class/getResource/src/m2/p2/impl/Type.java
index 9d2c8be..93a3e31 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/Class/getResource/src/m2/p2/impl/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p2.impl;
+
+public class Type { }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/Class/getResource/src/m2/p2/resources/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/Class/getResource/src/m2/p2/resources/Type.java
index 9d2c8be..fa35bbf 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/Class/getResource/src/m2/p2/resources/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p2.resources;
+
+public class Type { }
diff --git a/jdk/test/java/lang/Class/getResource/src/m3/module-info.java b/jdk/test/java/lang/Class/getResource/src/m3/module-info.java
deleted file mode 100644
index f9754a0..0000000
--- a/jdk/test/java/lang/Class/getResource/src/m3/module-info.java
+++ /dev/null
@@ -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 p3;
-}
diff --git a/jdk/test/java/lang/Class/getResource/src/m3/p3/Main.java b/jdk/test/java/lang/Class/getResource/src/m3/p3/Main.java
deleted file mode 100644
index 08062e1..0000000
--- a/jdk/test/java/lang/Class/getResource/src/m3/p3/Main.java
+++ /dev/null
@@ -1,39 +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 p3;
-
-import java.io.InputStream;
-import java.net.URL;
-
-public class Main {
-    private Main() { }
-
-    public static URL getResource(String name) {
-        return Main.class.getResource(name);
-    }
-
-    public static InputStream getResourceAsStream(String name) {
-        return Main.class.getResourceAsStream(name);
-    }
-}
diff --git a/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java b/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java
index 684ccb2..85c21d2 100644
--- a/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java
+++ b/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java
@@ -28,6 +28,7 @@
  *          Quoted entries should get unquoted on Windows.
  *          Empty entries should be replaced with dot.
  * @library /lib/testlibrary
+ * @modules java.base/java.lang:open
  * @build jdk.testlibrary.Platform
  * @run main LibraryPathProperty
  */
diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh
index a00c140..ffaf9f3 100644
--- a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh
+++ b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh
@@ -106,6 +106,7 @@
 # run test
 ${TESTJAVA}${FS}bin${FS}java \
         ${TESTVMOPTS} \
+        --add-opens java.base/java.lang=ALL-UNNAMED \
         -verbose:class -Xlog:class+load -cp . \
         -Dtest.classes=${TESTCLASSES} \
         Starter cross
diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh
index 1289b4c..b080e01 100644
--- a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh
+++ b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh
@@ -102,6 +102,7 @@
 # run test
 ${TESTJAVA}${FS}bin${FS}java \
         ${TESTVMOPTS} \
+        --add-opens java.base/java.lang=ALL-UNNAMED \
         -verbose:class -Xlog:class+load -cp . \
         -Dtest.classes=${TESTCLASSES} \
         Starter one-way
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java b/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java
index a6436af..e816f31 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/Main.java
@@ -21,13 +21,18 @@
  * questions.
  */
 
+import java.io.InputStream;
 import java.lang.module.Configuration;
 import java.lang.module.ResolvedModule;
 import java.lang.reflect.Layer;
 import java.io.IOException;
+import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
 
 /**
  * Basic test of ClassLoader getResource and getResourceAsStream when
@@ -40,36 +45,242 @@
 
     public static void main(String[] args) throws IOException {
 
-        // create m1/myresource containing "m1"
-        Path file = directoryFor("m1").resolve(NAME);
-        Files.write(file, "m1".getBytes("UTF-8"));
+        // create resources in m1
+        createResource("m1", Paths.get("."), "m1");
+        createResource("m1", Paths.get("p1"), "m1/p1");
+        createResource("m1", Paths.get("p1", "impl"), "m1/p1.impl");
+        createResource("m1", Paths.get("p1", "resources"), "m1/p1.resources");
 
-        // create m2/myresource containing "m2"
-        file = directoryFor("m2").resolve(NAME);
-        Files.write(file, "m2".getBytes("UTF-8"));
+        // create resources in m2
+        createResource("m2", Paths.get("."), "m2");
+        createResource("m2", Paths.get("p2"), "m2/p2");
+        createResource("m2", Paths.get("p2", "impl"), "m2/p2.impl");
+        createResource("m2", Paths.get("p2", "resources"), "m2/p2.resources");
 
-        // check that m3/myresource does not exist
-        assertTrue(Files.notExists(directoryFor("m3").resolve(NAME)));
 
         // invoke ClassLoader getResource from the unnamed module
-        assertNull(Main.class.getClassLoader().getResource("/" + NAME));
+        ClassLoader thisLoader = Main.class.getClassLoader();
 
-        // invoke ClassLoader getResource from modules m1-m3
-        // Resources in a named module are private to that module.
-        // ClassLoader.getResource should not find resource in named modules.
-        assertNull(p1.Main.getResourceInClassLoader("/" + NAME));
-        assertNull(p2.Main.getResourceInClassLoader("/" + NAME));
-        assertNull(p3.Main.getResourceInClassLoader("/" + NAME));
+        URL url = thisLoader.getResource(NAME);
+        assertNotNull(url);
+
+        url = thisLoader.getResource("p1/" + NAME);
+        assertNull(url);
+
+        url = thisLoader.getResource("p1/impl/" + NAME);
+        assertNull(url);
+
+        url = thisLoader.getResource("p1/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.resources");
+
+        url = thisLoader.getResource("p2/" + NAME);
+        assertNull(url);
+
+        url = thisLoader.getResource("p2/impl/" + NAME);
+        assertNull(url);
+
+        url = thisLoader.getResource("p2/resources/" + NAME);
+        assertNull(url);
+
+
+        // invoke ClassLoader getResource from module m1
+        url = p1.Main.getResourceInClassLoader(NAME);
+        assertNotNull(url);
+
+        url = p1.Main.getResourceInClassLoader("p1/" + NAME);
+        assertNull(url);
+
+        url = p1.Main.getResourceInClassLoader("p1/impl/" + NAME);
+        assertNull(url);
+
+        url = p1.Main.getResourceInClassLoader("p1/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.resources");
+
+        url = p1.Main.getResourceInClassLoader("p2/" + NAME);
+        assertNull(url);
+
+        url = p1.Main.getResourceInClassLoader("p2/impl/" + NAME);
+        assertNull(url);
+
+        url = p1.Main.getResourceInClassLoader("p2/resources/" + NAME);
+        assertNull(url);
+
+
+        // invoke ClassLoader getResource from module m2
+        url = p2.Main.getResourceInClassLoader(NAME);
+        assertNotNull(url);
+
+        url = p2.Main.getResourceInClassLoader("p1/" + NAME);
+        assertNull(url);
+
+        url = p2.Main.getResourceInClassLoader("p1/impl/" + NAME);
+        assertNull(url);
+
+        url = p2.Main.getResourceInClassLoader("p1/resources/" + NAME);
+        assertEquals(readAllAsString(url), "m1/p1.resources");
+
+        url = p2.Main.getResourceInClassLoader("p2/" + NAME);
+        assertNull(url);
+
+        url = p2.Main.getResourceInClassLoader("p2/impl/" + NAME);
+        assertNull(url);
+
+        url = p2.Main.getResourceInClassLoader("p2/resources/" + NAME);
+        assertNull(url);
+
+
+        // invoke ClassLoader getResources from the unnamed module
+        Enumeration<URL> urls = thisLoader.getResources(NAME);
+        List<String> resources = readAllAsStrings(urls);
+        assertTrue(resources.size() == 2);
+        assertTrue(resources.contains("m1"));
+        assertTrue(resources.contains("m2"));
+
+        urls = thisLoader.getResources("p1/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = thisLoader.getResources("p1/impl/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = thisLoader.getResources("p1/resources/" + NAME);
+        resources = readAllAsStrings(urls);
+        assertTrue(resources.size() == 1);
+        assertTrue(resources.contains("m1/p1.resources"));
+
+        urls = thisLoader.getResources("p2/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = thisLoader.getResources("p2/impl/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = thisLoader.getResources("p2/resources/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+
+        // invoke ClassLoader getResources from m1
+        urls = p1.Main.getResourcesInClassLoader(NAME);
+        resources = readAllAsStrings(urls);
+        assertTrue(resources.size() == 2);
+        assertTrue(resources.contains("m1"));
+        assertTrue(resources.contains("m2"));
+
+        urls = p1.Main.getResourcesInClassLoader("p1/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p1.Main.getResourcesInClassLoader("p1/impl/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p1.Main.getResourcesInClassLoader("p1/resources/" + NAME);
+        resources = readAllAsStrings(urls);
+        assertTrue(resources.size() == 1);
+        assertTrue(resources.contains("m1/p1.resources"));
+
+        urls = p1.Main.getResourcesInClassLoader("p2/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p1.Main.getResourcesInClassLoader("p2/impl/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p1.Main.getResourcesInClassLoader("p2/resources/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+
+        // invoke ClassLoader getResources from m2
+        urls = p2.Main.getResourcesInClassLoader(NAME);
+        resources = readAllAsStrings(urls);
+        assertTrue(resources.size() == 2);
+        assertTrue(resources.contains("m1"));
+        assertTrue(resources.contains("m2"));
+
+        urls = p2.Main.getResourcesInClassLoader("p1/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p2.Main.getResourcesInClassLoader("p1/impl/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p2.Main.getResourcesInClassLoader("p1/resources/" + NAME);
+        resources = readAllAsStrings(urls);
+        assertTrue(resources.size() == 1);
+        assertTrue(resources.contains("m1/p1.resources"));
+
+        urls = p2.Main.getResourcesInClassLoader("p2/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p2.Main.getResourcesInClassLoader("p2/impl/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
+        urls = p2.Main.getResourcesInClassLoader("p2/resources/" + NAME);
+        assertTrue(readAllAsStrings(urls).isEmpty());
+
 
         // invoke ClassLoader getResourceAsStream from the unnamed module
-        assertNull(Main.class.getClassLoader().getResourceAsStream("/" + NAME));
+        InputStream in = thisLoader.getResourceAsStream(NAME);
+        assertNotNull(in);
 
-        // invoke ClassLoader getResourceAsStream from modules m1-m3
-        // Resources in a named module are private to that module.
-        // ClassLoader.getResourceAsStream should not find resource in named modules.
-        assertNull(p1.Main.getResourceAsStreamInClassLoader("/" + NAME));
-        assertNull(p2.Main.getResourceAsStreamInClassLoader("/" + NAME));
-        assertNull(p3.Main.getResourceAsStreamInClassLoader("/" + NAME));
+        in = thisLoader.getResourceAsStream("p1/" + NAME);
+        assertNull(in);
+
+        in = thisLoader.getResourceAsStream("p1/impl/" + NAME);
+        assertNull(in);
+
+        in = thisLoader.getResourceAsStream("p1/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.resources");
+
+        in = thisLoader.getResourceAsStream("p2/" + NAME);
+        assertNull(in);
+
+        in = thisLoader.getResourceAsStream("p2/impl/" + NAME);
+        assertNull(in);
+
+        in = thisLoader.getResourceAsStream("p2/resources/" + NAME);
+        assertNull(in);
+
+
+        // invoke ClassLoader getResource from modules m1
+        in = p1.Main.getResourceAsStreamInClassLoader(NAME);
+        assertNotNull(in);
+
+        in = p1.Main.getResourceAsStreamInClassLoader("p1/" + NAME);
+        assertNull(in);
+
+        in = p1.Main.getResourceAsStreamInClassLoader("p1/impl/" + NAME);
+        assertNull(in);
+
+        in = p1.Main.getResourceAsStreamInClassLoader("p1/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.resources");
+
+        in = p1.Main.getResourceAsStreamInClassLoader("p2/" + NAME);
+        assertNull(in);
+
+        in = p1.Main.getResourceAsStreamInClassLoader("p2/impl/" + NAME);
+        assertNull(in);
+
+        in = p1.Main.getResourceAsStreamInClassLoader("p2/resources/" + NAME);
+        assertNull(in);
+
+
+        // invoke ClassLoader getResource from modules m2
+        in = p2.Main.getResourceAsStreamInClassLoader(NAME);
+        assertNotNull(in);
+
+        in = p2.Main.getResourceAsStreamInClassLoader("p1/" + NAME);
+        assertNull(in);
+
+        in = p2.Main.getResourceAsStreamInClassLoader("p1/impl/" + NAME);
+        assertNull(in);
+
+        in = p2.Main.getResourceAsStreamInClassLoader("p1/resources/" + NAME);
+        assertEquals(readAllAsString(in), "m1/p1.resources");
+
+        in = p2.Main.getResourceAsStreamInClassLoader("p2/" + NAME);
+        assertNull(in);
+
+        in = p2.Main.getResourceAsStreamInClassLoader("p2/impl/" + NAME);
+        assertNull(in);
+
+        in = p2.Main.getResourceAsStreamInClassLoader("p2/resources/" + NAME);
+        assertNull(in);
+
 
         // SecurityManager case
         System.setSecurityManager(new SecurityManager());
@@ -77,17 +288,24 @@
         assertNull(Main.class.getClassLoader().getResource("/" + NAME));
         assertNull(p1.Main.getResourceInClassLoader("/" + NAME));
         assertNull(p2.Main.getResourceInClassLoader("/" + NAME));
-        assertNull(p3.Main.getResourceInClassLoader("/" + NAME));
 
         assertNull(Main.class.getClassLoader().getResourceAsStream("/" + NAME));
         assertNull(p1.Main.getResourceAsStreamInClassLoader("/" + NAME));
         assertNull(p2.Main.getResourceAsStreamInClassLoader("/" + NAME));
-        assertNull(p3.Main.getResourceAsStreamInClassLoader("/" + NAME));
 
         System.out.println("Success!");
     }
 
     /**
+     * Create a resource in the sub-directory of the given exploded module
+     */
+    static void createResource(String mn, Path subdir, String msg) throws IOException {
+        Path dir = directoryFor(mn).resolve(subdir);
+        Path file = dir.resolve(NAME);
+        Files.write(file, msg.getBytes("UTF-8"));
+    }
+
+    /**
      * Returns the directory for the given module (by name).
      */
     static Path directoryFor(String mn) {
@@ -101,12 +319,60 @@
         return dir;
     }
 
+    static String readAllAsString(InputStream in) throws IOException {
+        if (in == null)
+            return null;
+        try (in) {
+            return new String(in.readAllBytes(), "UTF-8");
+        }
+    }
+
+    static String readAllAsString(URL url) throws IOException {
+        if (url == null)
+            return null;
+        InputStream in = url.openStream();
+        return readAllAsString(url.openStream());
+    }
+
+    static List<String> readAllAsStrings(Enumeration<URL> urls) throws IOException {
+        List<String> result = new ArrayList<>();
+        while (urls.hasMoreElements()) {
+            URL url = urls.nextElement();
+            result.add(readAllAsString(url));
+        }
+        return result;
+    }
+
     static void assertTrue(boolean condition) {
         if (!condition) throw new RuntimeException();
     }
 
+    static void assertFalse(boolean condition) {
+        if (condition) throw new RuntimeException();
+    }
+
     static void assertNull(Object o) {
         assertTrue(o == null);
     }
+
+    static void assertNotNull(Object o) {
+        assertTrue(o != null);
+    }
+
+    static void assertEquals(Object actual, Object expected) {
+        if (expected == null) {
+            assertNull(actual);
+        } else {
+            assertTrue(expected.equals(actual));
+        }
+    }
+
+    static void assertNotEquals(Object actual, Object expected) {
+        if (expected == null) {
+            assertNotNull(actual);
+        } else {
+            assertTrue(!expected.equals(actual));
+        }
+    }
 }
 
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java b/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java
index 3eafa82..65f0d37 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/ResourcesTest.java
@@ -68,7 +68,7 @@
             .compile(Paths.get(TEST_SRC, "Main.java"),
                      CLASSES_DIR,
                      "--module-path", MODS_DIR.toString(),
-                     "--add-modules", "m1,m2,m3");
+                     "--add-modules", "m1,m2");
         assertTrue(compiled);
     }
 
@@ -78,7 +78,7 @@
     public void runTest() throws Exception {
         int exitValue
             = executeTestJava("--module-path", MODS_DIR.toString(),
-                              "--add-modules", "m1,m2,m3",
+                              "--add-modules", "m1,m2",
                                "-cp", CLASSES_DIR.toString(),
                               "Main")
                 .outputTo(System.out)
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/module-info.java
index 47a2c4c..e29065e 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/module-info.java
@@ -23,4 +23,5 @@
 
 module m1 {
     exports p1;
+    opens p1.resources;
 }
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/Main.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/Main.java
index 9e14eb0..9d5c3ea0 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/Main.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/Main.java
@@ -24,7 +24,9 @@
 package p1;
 
 import java.io.InputStream;
+import java.io.IOException;
 import java.net.URL;
+import java.util.Enumeration;
 
 public class Main {
     private Main() { }
@@ -33,6 +35,10 @@
         return Main.class.getClassLoader().getResource(name);
     }
 
+    public static Enumeration<URL> getResourcesInClassLoader(String name) throws IOException {
+        return Main.class.getClassLoader().getResources(name);
+    }
+
     public static InputStream getResourceAsStreamInClassLoader(String name) {
         return Main.class.getClassLoader().getResourceAsStream(name);
     }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/impl/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/impl/Type.java
index 9d2c8be..12820db 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/impl/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p1.impl;
+
+public class Type { }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/resources/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/resources/Type.java
index 9d2c8be..6dcc132 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m1/p1/resources/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p1.resources;
+
+public class Type { }
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/module-info.java
index e28b220..6b7c3ef 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/module-info.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/module-info.java
@@ -23,4 +23,6 @@
 
 module m2 {
     exports p2;
+    exports p2.impl to m1;
+    opens p2.resources to m1;
 }
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/Main.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/Main.java
index 6f291a2..e3d61be 100644
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/Main.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/Main.java
@@ -24,7 +24,9 @@
 package p2;
 
 import java.io.InputStream;
+import java.io.IOException;
 import java.net.URL;
+import java.util.Enumeration;
 
 public class Main {
     private Main() { }
@@ -33,6 +35,10 @@
         return Main.class.getClassLoader().getResource(name);
     }
 
+    public static Enumeration<URL> getResourcesInClassLoader(String name) throws IOException {
+        return Main.class.getClassLoader().getResources(name);
+    }
+
     public static InputStream getResourceAsStreamInClassLoader(String name) {
         return Main.class.getClassLoader().getResourceAsStream(name);
     }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/impl/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/impl/Type.java
index 9d2c8be..93a3e31 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/impl/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p2.impl;
+
+public class Type { }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/resources/Type.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/resources/Type.java
index 9d2c8be..fa35bbf 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m2/p2/resources/Type.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p2.resources;
+
+public class Type { }
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/module-info.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/module-info.java
deleted file mode 100644
index f9754a0..0000000
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/module-info.java
+++ /dev/null
@@ -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 p3;
-}
diff --git a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/p3/Main.java b/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/p3/Main.java
deleted file mode 100644
index 55a23b9..0000000
--- a/jdk/test/java/lang/ClassLoader/getResource/modules/src/m3/p3/Main.java
+++ /dev/null
@@ -1,39 +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 p3;
-
-import java.io.InputStream;
-import java.net.URL;
-
-public class Main {
-    private Main() { }
-
-    public static URL getResourceInClassLoader(String name) {
-        return Main.class.getClassLoader().getResource(name);
-    }
-
-    public static InputStream getResourceAsStreamInClassLoader(String name) {
-        return Main.class.getClassLoader().getResourceAsStream(name);
-    }
-}
diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java
index c04e085..729b249 100644
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java
@@ -29,6 +29,7 @@
  *      4947220 7018606 7034570 4244896 5049299 8003488 8054494 8058464
  *      8067796
  * @summary Basic tests for Process and Environment Variable code
+ * @modules java.base/java.lang:open
  * @run main/othervm/timeout=300 Basic
  * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic
  * @author Martin Buchholz
diff --git a/jdk/test/java/lang/Runtime/Version/VersionProps.java b/jdk/test/java/lang/Runtime/Version/VersionProps.java
index ddbaa08..b0c98d2 100644
--- a/jdk/test/java/lang/Runtime/Version/VersionProps.java
+++ b/jdk/test/java/lang/Runtime/Version/VersionProps.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8160564
  * @summary check the implementation of VersionProps.versionNumbers()
+ * @modules java.base/java.lang:open
  * @run main VersionProps
  * @author Volker Simonis
  */
diff --git a/jdk/test/java/lang/StackWalker/CountLocalSlots.java b/jdk/test/java/lang/StackWalker/CountLocalSlots.java
index 066055b..dfb1698 100644
--- a/jdk/test/java/lang/StackWalker/CountLocalSlots.java
+++ b/jdk/test/java/lang/StackWalker/CountLocalSlots.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8147039
  * @summary Confirm locals[] always has expected length, even for "dead" locals
+ * @modules java.base/java.lang:open
  * @compile LocalsAndOperands.java
  * @run testng/othervm -Xcomp CountLocalSlots
  */
diff --git a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java
index f4f6465..ab07c7d 100644
--- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java
+++ b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8020968 8147039
  * @summary Tests for locals and operands
+ * @modules java.base/java.lang:open
  * @run testng LocalsAndOperands
  */
 
diff --git a/jdk/test/java/lang/StackWalker/LocalsCrash.java b/jdk/test/java/lang/StackWalker/LocalsCrash.java
index 87415e4..178e07c 100644
--- a/jdk/test/java/lang/StackWalker/LocalsCrash.java
+++ b/jdk/test/java/lang/StackWalker/LocalsCrash.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8147039
  * @summary Test for -Xcomp crash that happened before 8147039 fix
+ * @modules java.base/java.lang:open
  * @run testng/othervm -Xcomp LocalsCrash
  */
 
diff --git a/jdk/test/java/lang/String/CompactString/VMOptionsTest.java b/jdk/test/java/lang/String/CompactString/VMOptionsTest.java
index 01eed44..04fc008 100644
--- a/jdk/test/java/lang/String/CompactString/VMOptionsTest.java
+++ b/jdk/test/java/lang/String/CompactString/VMOptionsTest.java
@@ -37,6 +37,7 @@
  *          if Compact String enable/disable VM Options is indeed working in String class,
  *          it's verified by testing if the VM option affect coder and
  *          COMPACT_STRINGS field in String class.
+ * @modules java.base/java.lang:open
  * @run testng/othervm -XX:+CompactStrings -DCompactStringEnabled=true VMOptionsTest
  * @run testng/othervm -XX:-CompactStrings -DCompactStringEnabled=false VMOptionsTest
  */
diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java
index bedd611..1b6a5c6 100644
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java
@@ -39,7 +39,7 @@
  * @bug     8144460 8144214
  * @summary Cover the logXX and LogEvent.valueOf APIs of BootstrapLogger
  *          and logXX APIs of SimpleConsoleLogger.
- * @modules java.base/jdk.internal.logger
+ * @modules java.base/jdk.internal.logger:+open
  *          java.base/sun.util.logging
  * @build BootstrapLoggerUtils LogStream
  * @run main/othervm BootstrapLoggerAPIsTest
diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java
index e2f6d4b..f34ab76 100644
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java
@@ -52,7 +52,7 @@
  * @summary JDK implementation specific unit test for JDK internal artifacts.
             Tests the behavior of bootstrap loggers (and SimpleConsoleLoggers
  *          too).
- * @modules java.base/jdk.internal.logger
+ * @modules java.base/jdk.internal.logger:+open
  *          java.logging
  * @build BootstrapLoggerUtils LogStream
  * @run main/othervm BootstrapLoggerTest NO_SECURITY
diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/SystemLoggerInPlatformLoader/SystemLoggerInPlatformLoader.java b/jdk/test/java/lang/System/LoggerFinder/internal/SystemLoggerInPlatformLoader/SystemLoggerInPlatformLoader.java
index 28bca5c..0262efa 100644
--- a/jdk/test/java/lang/System/LoggerFinder/internal/SystemLoggerInPlatformLoader/SystemLoggerInPlatformLoader.java
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/SystemLoggerInPlatformLoader/SystemLoggerInPlatformLoader.java
@@ -34,6 +34,7 @@
  * @test 8163162
  * @summary Checks that LazyLoggers are returned for System.Logger instances
  *          created by modules in the platform class loader.
+ * @modules java.base/java.lang:open
  * @build systempkg.log.SystemLoggerAccessor SystemLoggerInPlatformLoader
  * @run main/othervm SystemLoggerInPlatformLoader
  * @author danielfuchs
diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java
index eb3f07c..6abc3c5 100644
--- a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java
@@ -38,7 +38,8 @@
  *           It calls both the {@link java.lang.System} factory methods and
  *           {@link jdk.internal.logger.LazyLoggers} to obtains those loggers,
  *           and configure them with all possible known levels.
- * @modules java.base/sun.util.logging
+ * @modules java.base/java.lang:open
+ *          java.base/sun.util.logging
  *          java.base/jdk.internal.logger
  *          java.logging/sun.util.logging.internal
  * @build LoggerFinderBackendTest SystemClassLoader
diff --git a/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java b/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
index 982852c..586c0e4 100644
--- a/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
+++ b/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
@@ -27,7 +27,8 @@
  * @summary Test inheritance, order and class redefinition behaviour of RUNTIME
  *          class annotations
  * @author plevart
- * @modules java.base/sun.reflect.annotation
+ * @modules java.base/java.lang:open
+ *          java.base/sun.reflect.annotation
  */
 
 import sun.reflect.annotation.AnnotationParser;
diff --git a/jdk/test/java/lang/instrument/RedefineModuleAgent.java b/jdk/test/java/lang/instrument/RedefineModuleAgent.java
new file mode 100644
index 0000000..8d96db1
--- /dev/null
+++ b/jdk/test/java/lang/instrument/RedefineModuleAgent.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Module;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Agent used by RedefineModuleTest
+ */
+
+public class RedefineModuleAgent {
+
+    private static Instrumentation inst;
+
+    public static void premain(String args, Instrumentation inst) throws Exception {
+        RedefineModuleAgent.inst = inst;
+    }
+
+    static void redefineModule(Module module,
+                               Set<Module> extraReads,
+                               Map<String, Set<Module>> extraExports,
+                               Map<String, Set<Module>> extraOpens,
+                               Set<Class<?>> extraUses,
+                               Map<Class<?>, List<Class<?>>> extraProvides) {
+        inst.redefineModule(module, extraReads, extraExports, extraOpens, extraUses, extraProvides);
+    }
+}
diff --git a/jdk/test/java/lang/instrument/RedefineModuleTest.java b/jdk/test/java/lang/instrument/RedefineModuleTest.java
new file mode 100644
index 0000000..bf54daf
--- /dev/null
+++ b/jdk/test/java/lang/instrument/RedefineModuleTest.java
@@ -0,0 +1,369 @@
+/*
+ * 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 Basic test for redefineModule
+ * @modules java.instrument
+ * @build java.base/java.lang.TestProvider
+ *        java.base/jdk.internal.test.TestProviderImpl1
+ *        java.base/jdk.internal.test.TestProviderImpl2
+ * @run shell MakeJAR3.sh RedefineModuleAgent
+ * @run testng/othervm -javaagent:RedefineModuleAgent.jar RedefineModuleTest
+ */
+
+import java.lang.TestProvider;
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.net.URLStreamHandler;
+import java.net.spi.URLStreamHandlerProvider;
+import java.nio.file.FileSystems;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class RedefineModuleTest {
+
+    static void redefineModule(Module module,
+                               Set<Module> extraReads,
+                               Map<String, Set<Module>> extraExports,
+                               Map<String, Set<Module>> extraOpens,
+                               Set<Class<?>> extraUses,
+                               Map<Class<?>, List<Class<?>>> extraProvides) {
+        RedefineModuleAgent.redefineModule(module,
+                                           extraReads,
+                                           extraExports,
+                                           extraOpens,
+                                           extraUses,
+                                           extraProvides);
+    }
+
+
+    /**
+     * Use redefineModule to update java.base to read java.instrument
+     */
+    public void testAddReads() {
+        Module baseModule = Object.class.getModule();
+        Module instrumentModule = Instrumentation.class.getModule();
+
+        // pre-conditions
+        assertFalse(baseModule.canRead(instrumentModule));
+
+        // update java.base to read java.instrument
+        Set<Module> extraReads = Set.of(instrumentModule);
+        redefineModule(baseModule, extraReads, Map.of(), Map.of(), Set.of(), Map.of());
+        assertTrue(baseModule.canRead(instrumentModule));
+    }
+
+    /**
+     * Use redefineModule to update java.base to export jdk.internal.misc
+     */
+    public void testAddExports() {
+        Module baseModule = Object.class.getModule();
+        Module thisModule = this.getClass().getClassLoader().getUnnamedModule();
+        String pkg = "jdk.internal.misc";
+
+        // pre-conditions
+        assertFalse(baseModule.isExported(pkg));
+        assertFalse(baseModule.isExported(pkg, thisModule));
+
+        // update java.base to export jdk.internal.misc to an unnamed module
+        Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of(thisModule));
+        redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
+        assertFalse(baseModule.isExported(pkg));
+        assertTrue(baseModule.isExported(pkg, thisModule));
+        assertFalse(baseModule.isOpen(pkg));
+        assertFalse(baseModule.isOpen(pkg, thisModule));
+    }
+
+    /**
+     * Use redefineModule to update java.base to open jdk.internal.loader
+     */
+    public void testAddOpens() {
+        Module baseModule = Object.class.getModule();
+        Module thisModule = this.getClass().getClassLoader().getUnnamedModule();
+        String pkg = "jdk.internal.loader";
+
+        // pre-conditions
+        assertFalse(baseModule.isOpen(pkg));
+        assertFalse(baseModule.isOpen(pkg, thisModule));
+
+        // update java.base to open dk.internal.loader to an unnamed module
+        Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of(thisModule));
+        redefineModule(baseModule, Set.of(), Map.of(), extraExports, Set.of(), Map.of());
+        assertFalse(baseModule.isExported(pkg));
+        assertTrue(baseModule.isExported(pkg, thisModule));
+        assertFalse(baseModule.isOpen(pkg));
+        assertTrue(baseModule.isOpen(pkg, thisModule));
+    }
+
+    /**
+     * Use redefineModule to update java.base to use TestProvider and
+     * provide implementations of TestProvider.
+     */
+    public void testAddUsesAndProvides() throws Exception {
+        Module baseModule = Object.class.getModule();
+        Class<TestProvider> service = TestProvider.class;
+
+        // pre-conditions
+        assertFalse(baseModule.canUse(service));
+        assertTrue(collect(ServiceLoader.load(service)).isEmpty());
+        assertTrue(collect(ServiceLoader.load(Layer.boot(), service)).isEmpty());
+
+        // update java.base to use TestProvider
+        redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(service), Map.of());
+        assertTrue(baseModule.canUse(service));
+        assertTrue(collect(ServiceLoader.load(service)).isEmpty());
+        assertTrue(collect(ServiceLoader.load(Layer.boot(), service)).isEmpty());
+
+        // update java.base to provide an implementation of TestProvider
+        Class<?> type1 = Class.forName("jdk.internal.test.TestProviderImpl1");
+        Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of(type1));
+        redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+
+        // invoke ServiceLoader from java.base to find providers
+        Set<TestProvider> providers = collect(TestProvider.providers());
+        assertTrue(providers.size() == 1);
+        assertTrue(containsInstanceOf(providers, type1));
+
+        // use ServiceLoader to load implementations visible via TCCL
+        providers = collect(ServiceLoader.load(service));
+        assertTrue(collect(providers).size() == 1);
+        assertTrue(containsInstanceOf(collect(providers), type1));
+
+        // use ServiceLoader to load implementations in the boot layer
+        providers = collect(ServiceLoader.load(Layer.boot(), service));
+        assertTrue(collect(providers).size() == 1);
+        assertTrue(containsInstanceOf(collect(providers), type1));
+
+        // update java.base to provide a second implementation of TestProvider
+        Class<?> type2 = Class.forName("jdk.internal.test.TestProviderImpl2");
+        extraProvides = Map.of(service, List.of(type2));
+        redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+
+        // invoke ServiceLoader from java.base to find providers
+        providers = collect(TestProvider.providers());
+        assertTrue(providers.size() == 2);
+        assertTrue(containsInstanceOf(providers, type1));
+        assertTrue(containsInstanceOf(providers, type2));
+
+        // use ServiceLoader to load implementations visible via TCCL
+        providers = collect(ServiceLoader.load(service));
+        assertTrue(collect(providers).size() == 2);
+        assertTrue(containsInstanceOf(providers, type1));
+        assertTrue(containsInstanceOf(providers, type2));
+
+        // use ServiceLoader to load implementations in the boot layer
+        providers = collect(ServiceLoader.load(Layer.boot(), service));
+        assertTrue(collect(providers).size() == 2);
+        assertTrue(containsInstanceOf(providers, type1));
+        assertTrue(containsInstanceOf(providers, type2));
+    }
+
+    private <S> Set<S> collect(Iterable<S> sl) {
+        Set<S> providers = new HashSet<>();
+        sl.forEach(providers::add);
+        return providers;
+    }
+
+    private boolean containsInstanceOf(Collection<?> c, Class<?> type) {
+        for (Object o : c) {
+            if (type.isInstance(o)) return true;
+        }
+        return false;
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testExportPackageToEmptySet() {
+        // attempt to update java.base to export jdk.internal.misc to nobody
+        Module baseModule = Object.class.getModule();
+        Map<String, Set<Module>> extraExports = Map.of("jdk.internal.misc", Set.of());
+        redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testOpenPackageToEmptySet() {
+        // attempt to update java.base to open jdk.internal.misc to nobody
+        Module baseModule = Object.class.getModule();
+        Map<String, Set<Module>> extraOpens = Map.of("jdk.internal.misc", Set.of());
+        redefineModule(baseModule, Set.of(), Map.of(), extraOpens, Set.of(), Map.of());
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testProvideServiceWithEmptyList() throws Exception {
+        // update java.base to provide an empty list of TestProvider
+        Module baseModule = Object.class.getModule();
+        Class<?> service = TestProvider.class;
+        Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of());
+        redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+    }
+
+    /**
+     * Test redefineClass by attempting to update java.base to export a package
+     * that it does not contain.
+     */
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testExportPackageNotInModule() {
+        Module baseModule = Object.class.getModule();
+        String pkg = "jdk.doesnotexist";
+
+        // attempt to update java.base to export jdk.doesnotexist
+        Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of());
+        redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
+    }
+
+    /**
+     * Test redefineClass by attempting to update java.base to provide a service
+     * where the service provider class is not in the module.
+     */
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testProvideServiceNotInModule() {
+        Module baseModule = Object.class.getModule();
+        class MyProvider extends URLStreamHandlerProvider {
+            @Override
+            public URLStreamHandler createURLStreamHandler(String protocol) {
+                return null;
+            }
+        }
+
+        // attempt to update java.base to provide MyProvider
+        Map<Class<?>, List<Class<?>>> extraProvides
+            = Map.of(URLStreamHandlerProvider.class, List.of(MyProvider.class));
+        redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+    }
+
+    /**
+     * Test redefineClass by attempting to update java.base to provide a
+     * service where the service provider class is not a sub-type.
+     */
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testProvideServiceNotSubtype() {
+        Module baseModule = Object.class.getModule();
+
+        Class<?> service = TestProvider.class;
+        Class<?> impl = FileSystems.getDefault().provider().getClass();
+
+        // attempt to update java.base to provide an implementation of TestProvider
+        Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of(impl));
+        redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+    }
+
+    /**
+     * Test redefineClass with null
+     */
+    public void testNulls() {
+        Module baseModule = Object.class.getModule();
+
+        try {
+            redefineModule(null, Set.of(), Map.of(), Map.of(), Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            redefineModule(baseModule, null, Map.of(), Map.of(), Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            redefineModule(baseModule, Set.of(), null, Map.of(), Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            redefineModule(baseModule, Set.of(), Map.of(), null, Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            redefineModule(baseModule, Set.of(), Map.of(), Map.of(), null, Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), null);
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            Set<Module> containsNull = new HashSet<>();
+            containsNull.add(null);
+            redefineModule(baseModule, containsNull, Map.of(), Map.of(), Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            Map<String, Set<Module>> extraExports = new HashMap<>();
+            extraExports.put(null, Set.of());
+            redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            Map<String, Set<Module>> extraExports = new HashMap<>();
+            extraExports.put(null, Set.of());
+            redefineModule(baseModule, Set.of(), Map.of(), extraExports, Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            Set<Module> containsNull = new HashSet<>();
+            containsNull.add(null);
+            Map<String, Set<Module>> extraExports = Map.of("java.lang", containsNull);
+            redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            Set<Class<?>> containsNull = new HashSet<>();
+            containsNull.add(null);
+            redefineModule(baseModule, Set.of(), Map.of(), Map.of(), containsNull, Map.of());
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            Map<Class<?>, List<Class<?>>> extraProvides = new HashMap<>();
+            extraProvides.put(null, List.of());
+            redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+
+        try {
+            List<Class<?>> containsNull = new ArrayList<>();
+            containsNull.add(null);
+            Map<Class<?>, List<Class<?>>> extraProvides = Map.of(TestProvider.class, containsNull);
+            redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides);
+            assertTrue(false);
+        } catch (NullPointerException e) { }
+    }
+
+}
diff --git a/jdk/test/java/lang/instrument/TestAgentWithLimitMods.java b/jdk/test/java/lang/instrument/TestAgentWithLimitMods.java
index 1571774..4cdbeb6 100644
--- a/jdk/test/java/lang/instrument/TestAgentWithLimitMods.java
+++ b/jdk/test/java/lang/instrument/TestAgentWithLimitMods.java
@@ -28,7 +28,7 @@
  * the module graph
  * @modules java.instrument
  * @run shell MakeJAR3.sh SimpleAgent
- * @run main/othervm -javaagent:SimpleAgent.jar -limitmods java.base TestAgentWithLimitMods
+ * @run main/othervm -javaagent:SimpleAgent.jar --limit-modules java.base TestAgentWithLimitMods
  *
  */
 public class TestAgentWithLimitMods {
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/lang/instrument/java.base/java/lang/TestProvider.java
similarity index 83%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/lang/instrument/java.base/java/lang/TestProvider.java
index 242f168..696d2e9 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/lang/instrument/java.base/java/lang/TestProvider.java
@@ -21,5 +21,12 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package java.lang;
+
+import java.util.ServiceLoader;
+
+public interface TestProvider {
+    public static Iterable<TestProvider> providers() {
+        return ServiceLoader.load(TestProvider.class);
+    }
+}
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/lang/instrument/java.base/jdk/internal/test/TestProviderImpl1.java
similarity index 86%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/lang/instrument/java.base/jdk/internal/test/TestProviderImpl1.java
index 242f168..24eb296 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/lang/instrument/java.base/jdk/internal/test/TestProviderImpl1.java
@@ -21,5 +21,11 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package jdk.internal.test;
+
+import java.lang.TestProvider;
+
+public class TestProviderImpl1 implements TestProvider {
+    public TestProviderImpl1() { }
+}
+
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/lang/instrument/java.base/jdk/internal/test/TestProviderImpl2.java
similarity index 86%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/lang/instrument/java.base/jdk/internal/test/TestProviderImpl2.java
index 242f168..dd4be4e 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/lang/instrument/java.base/jdk/internal/test/TestProviderImpl2.java
@@ -21,5 +21,11 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package jdk.internal.test;
+
+import java.lang.TestProvider;
+
+public class TestProviderImpl2 implements TestProvider {
+    public TestProviderImpl2() { }
+}
+
diff --git a/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java b/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
index 464b275..d453caf 100644
--- a/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
+++ b/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java
@@ -28,7 +28,9 @@
  * @summary Test verifies that lambda forms are cached when run with multiple threads
  * @author kshefov
  * @library /lib/testlibrary/jsr292 /lib/testlibrary
- * @modules jdk.management
+ * @modules java.base/java.lang.invoke:open
+ *          java.base/java.lang.ref:open
+ *          jdk.management
  * @build TestMethods
  * @build LambdaFormTestCase
  * @build LFCachingTestCase
diff --git a/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java b/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
index 08bce54..bef4d5e 100644
--- a/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
+++ b/jdk/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java
@@ -28,6 +28,8 @@
  * @summary Test verifies that lambda forms are cached when run with single thread
  * @author kshefov
  * @library /lib/testlibrary/jsr292 /lib/testlibrary
+ * @modules java.base/java.lang.ref:open
+ *          java.base/java.lang.invoke:open
  * @build TestMethods
  * @build LambdaFormTestCase
  * @build LFCachingTestCase
diff --git a/jdk/test/java/lang/invoke/LambdaFormTest.java b/jdk/test/java/lang/invoke/LambdaFormTest.java
index f078189..5ebf2dd 100644
--- a/jdk/test/java/lang/invoke/LambdaFormTest.java
+++ b/jdk/test/java/lang/invoke/LambdaFormTest.java
@@ -23,6 +23,7 @@
 
 /* @test
  * @summary unit tests for java.lang.invoke.LambdaForm
+ * @modules java.base/java.lang.invoke:open
  * @run junit/othervm test.java.lang.invoke.LambdaFormTest
  */
 package test.java.lang.invoke;
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/Driver.java
similarity index 86%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/Driver.java
index 242f168..5abe4eb 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/Driver.java
@@ -21,5 +21,9 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+/**
+ * @test
+ * @build test/* m1/* m2/* m3/*
+ * @run testng/othervm test/p.PrivateLookupInTests
+ * @summary Unit tests for MethodHandles.privateLookupIn
+ */
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m1/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m1/module-info.java
index 9d2c8be..9f209a5 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m1/module-info.java
@@ -20,8 +20,5 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-module m1 {
-    requires unsupported;
-    exports p1;
+open module m1 {
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m1/p1/Type.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m1/p1/Type.java
index 9d2c8be..4517ab3 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m1/p1/Type.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p1;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class Type {
+    private static final Object obj = new Object();
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m2/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m2/module-info.java
index 9d2c8be..4a0a37a 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m2/module-info.java
@@ -20,8 +20,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-module m1 {
-    requires unsupported;
-    exports p1;
+module m2 {
+    opens p2 to test;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m2/p2/Type.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m2/p2/Type.java
index 9d2c8be..006eb3a 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m2/p2/Type.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p2;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class Type {
+    private static final Object obj = new Object();
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m3/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m3/module-info.java
index 9d2c8be..5603ddd 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m3/module-info.java
@@ -20,8 +20,5 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-module m1 {
-    requires unsupported;
-    exports p1;
+module m3 {
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m3/p3/Type.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m3/p3/Type.java
index 9d2c8be..0869c20 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/m3/p3/Type.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p3;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class Type {
+    private static final Object obj = new Object();
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/module-info.java
similarity index 91%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/module-info.java
index 9d2c8be..fd92c00 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/module-info.java
@@ -21,7 +21,7 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+module test {
+   requires testng;
+   exports p to testng;   // TestNG invokes the public methods
 }
diff --git a/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java
new file mode 100644
index 0000000..87dfbd7
--- /dev/null
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/PrivateLookupInTests.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General 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 p;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Module;
+
+import static java.lang.invoke.MethodHandles.Lookup.*;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * Unit tests for MethodHandles.privateLookupIn
+ */
+
+@Test
+public class PrivateLookupInTests {
+
+    /**
+     * A public and non-public types in the test module but in a different
+     * package to the test class.
+     *
+     * package p.internal;
+     * public class PublicType {
+     * }
+     *
+     * package p.internal;
+     * class NonPublicType {
+     *     private static final Object obj = ...
+     * }
+     */
+    private Class<?> publicType;
+    private Class<?> nonPublicType;
+
+    // initialize and sanity check publicType/nonPublicType
+    @BeforeTest
+    public void init() throws Exception {
+        publicType = Class.forName("p.internal.PublicType");
+        assertTrue(this.getClass().getModule() == publicType.getModule());
+        assertNotEquals(this.getClass().getPackageName(), publicType.getPackageName());
+        assertTrue(Modifier.isPublic(publicType.getModifiers()));
+
+        nonPublicType = Class.forName("p.internal.NonPublicType");
+        assertTrue(this.getClass().getModule() == nonPublicType.getModule());
+        assertNotEquals(this.getClass().getPackageName(), nonPublicType.getPackageName());
+        assertFalse(Modifier.isPublic(nonPublicType.getModifiers()));
+    }
+
+    // Invoke MethodHandles.privateLookupIn with a full-power caller
+    public void testAllAccessCallerSameModule() throws Throwable {
+        Lookup lookup = MethodHandles.privateLookupIn(nonPublicType, MethodHandles.lookup());
+        assertTrue(lookup.lookupClass() == nonPublicType);
+        assertTrue(lookup.hasPrivateAccess());
+
+        // get obj field
+        MethodHandle mh = lookup.findStaticGetter(nonPublicType, "obj", Object.class);
+        Object obj = mh.invokeExact();
+    }
+
+    // Invoke MethodHandles.privateLookupIn with a reduced-power caller
+    public void testReducedAccessCallerSameModule() throws Throwable {
+        // drop access
+        Lookup caller = MethodHandles.lookup().in(publicType);
+        assertTrue((caller.lookupModes() & PRIVATE) == 0);
+        assertTrue((caller.lookupModes() & PACKAGE) == 0);
+        assertTrue((caller.lookupModes() & MODULE) != 0);
+
+        Lookup lookup = MethodHandles.privateLookupIn(nonPublicType, caller);
+        assertTrue(lookup.lookupClass() == nonPublicType);
+        assertTrue(lookup.hasPrivateAccess());
+
+        // use it
+        MethodHandle mh = lookup.findStaticGetter(nonPublicType, "obj", Object.class);
+        Object obj = mh.invokeExact();
+    }
+
+    // Invoke MethodHandles.privateLookupIn with the public lookup as caller
+    @Test(expectedExceptions = {IllegalAccessException.class})
+    public void testPublicLookupSameModule() throws Exception {
+        Lookup caller = MethodHandles.publicLookup();
+        Lookup lookup = MethodHandles.privateLookupIn(publicType, caller);
+    }
+
+    // test reads m1, open module m1 containing p1
+    public void testTargetClassInOpenModule() throws Throwable {
+        // m1/p1.Type
+        Class<?> clazz = Class.forName("p1.Type");
+        assertEquals(clazz.getModule().getName(), "m1");
+
+        // ensure that this module reads m1
+        Module thisModule = getClass().getModule();
+        Module m1 = clazz.getModule();
+        thisModule.addReads(clazz.getModule());
+        assertTrue(m1.isOpen("p1", thisModule));
+
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        assertTrue(lookup.lookupClass() == clazz);
+        assertTrue(lookup.hasPrivateAccess());
+
+        // get obj field
+        MethodHandle mh = lookup.findStaticGetter(clazz, "obj", Object.class);
+        Object obj = mh.invokeExact();
+    }
+
+    // test does not read m2, m2 opens p2 to test
+    @Test(expectedExceptions = {IllegalAccessException.class})
+    public void testCallerDoesNotRead() throws Throwable {
+        // m2/p2.Type
+        Class<?> clazz = Class.forName("p2.Type");
+        assertEquals(clazz.getModule().getName(), "m2");
+
+        Module thisModule = getClass().getModule();
+        Module m2 = clazz.getModule();
+        assertFalse(thisModule.canRead(m2));
+        assertTrue(m2.isOpen("p2", thisModule));
+
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+    }
+
+    // test reads m3, m3 does not open p3 to test
+    @Test(expectedExceptions = {IllegalAccessException.class})
+    public void testNotOpenToCaller() throws Throwable {
+        // m3/p2.Type
+        Class<?> clazz = Class.forName("p3.Type");
+        assertEquals(clazz.getModule().getName(), "m3");
+
+        Module thisModule = getClass().getModule();
+        Module m3 = clazz.getModule();
+        thisModule.addReads(clazz.getModule());
+        assertFalse(m3.isOpen("p3", thisModule));
+
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+    }
+
+    // Invoke MethodHandles.privateLookupIn with a primitive class
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public void testPrimitiveClassAsTargetClass() throws Exception {
+        MethodHandles.privateLookupIn(int.class, MethodHandles.lookup());
+    }
+
+    // Invoke MethodHandles.privateLookupIn with an array class
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public void testArrayClassAsTargetClass() throws Exception {
+        MethodHandles.privateLookupIn(PrivateLookupInTests[].class, MethodHandles.lookup());
+    }
+
+    // Invoke MethodHandles.privateLookupIn with a primitive array class
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public void testPrimitiveArrayClassAsTargetClass() throws Exception {
+        MethodHandles.privateLookupIn(int[].class, MethodHandles.lookup());
+    }
+
+    // Invoke MethodHandles.privateLookupIn with null
+    @Test(expectedExceptions = {NullPointerException.class})
+    public void testNullTargetClass() throws Exception {
+        MethodHandles.privateLookupIn(null, MethodHandles.lookup());
+    }
+
+    // Invoke MethodHandles.privateLookupIn with null
+    @Test(expectedExceptions = {NullPointerException.class})
+    public void testNullCaller() throws Exception {
+        MethodHandles.privateLookupIn(getClass(), null);
+    }
+}
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/internal/NonPublicType.java
similarity index 90%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/internal/NonPublicType.java
index 242f168..5b7ce90 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/internal/NonPublicType.java
@@ -21,5 +21,9 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package p.internal;
+
+class NonPublicType {
+    private static final Object obj = new Object();
+}
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/internal/PublicType.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/internal/PublicType.java
index 9d2c8be..ff64d73 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/lang/invoke/MethodHandles/privateLookupIn/test/p/internal/PublicType.java
@@ -21,7 +21,8 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+package p.internal;
+
+public class PublicType {
 }
+
diff --git a/jdk/test/java/lang/invoke/PrivateInvokeTest.java b/jdk/test/java/lang/invoke/PrivateInvokeTest.java
index fdcb2ef..12edf8e 100644
--- a/jdk/test/java/lang/invoke/PrivateInvokeTest.java
+++ b/jdk/test/java/lang/invoke/PrivateInvokeTest.java
@@ -23,6 +23,7 @@
 
 /* @test
  * @summary white-box testing of method handle sub-primitives
+ * @modules java.base/java.lang.invoke:open
  * @run junit test.java.lang.invoke.PrivateInvokeTest
  */
 
diff --git a/jdk/test/java/lang/invoke/VMAnonymousClass.java b/jdk/test/java/lang/invoke/VMAnonymousClass.java
index 300e056..a76c496 100644
--- a/jdk/test/java/lang/invoke/VMAnonymousClass.java
+++ b/jdk/test/java/lang/invoke/VMAnonymousClass.java
@@ -32,7 +32,6 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import java.lang.reflect.Field;
 import org.junit.Test;
 import jdk.internal.misc.Unsafe;
 import jdk.internal.org.objectweb.asm.*;
@@ -64,7 +63,7 @@
        throw new RuntimeException("Expected SecurityException");
      }
 
-    private static Unsafe unsafe = getUnsafe();
+    private static Unsafe unsafe = Unsafe.getUnsafe();
 
     private static void test(String pkg) throws Throwable {
         byte[] bytes = dumpClass(pkg);
@@ -130,14 +129,4 @@
         cw.visitEnd();
         return cw.toByteArray();
     }
-
-    private static synchronized Unsafe getUnsafe() {
-        try {
-            Field f = Unsafe.class.getDeclaredField("theUnsafe");
-            f.setAccessible(true);
-            return (Unsafe) f.get(null);
-        } catch (NoSuchFieldException | IllegalAccessException e) {
-            throw new RuntimeException("Unable to get Unsafe instance.", e);
-        }
-    }
 }
diff --git a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
index 430591a..dc088b3 100644
--- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
+++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
@@ -127,8 +127,13 @@
                                "-Djdk.internal.lambda.dumpProxyClasses=dump",
                                "-Djava.security.manager",
                                "com.example.TestLambda");
-        // dump/com/example + 2 class files
-        assertEquals(Files.walk(Paths.get("dump")).count(), 5, "Two lambda captured");
+        // 2 our own class files. We don't care about the others
+        assertEquals(Files.find(
+                        Paths.get("dump"),
+                        99,
+                        (p, a) -> p.startsWith(Paths.get("dump/com/example"))
+                                && a.isRegularFile()).count(),
+                2, "Two lambda captured");
         tr.assertZero("Should still return 0");
     }
 
diff --git a/jdk/test/java/lang/module/AutomaticModulesTest.java b/jdk/test/java/lang/module/AutomaticModulesTest.java
index 3ad04a2..07d25b9 100644
--- a/jdk/test/java/lang/module/AutomaticModulesTest.java
+++ b/jdk/test/java/lang/module/AutomaticModulesTest.java
@@ -67,6 +67,15 @@
             // JAR file name                module-name[/version]
 
             { "foo.jar",                    "foo" },
+            { "foo4j.jar",                  "foo4j", },
+
+            { "foo1.jar",                   "foo" },
+            { "foo1.2.jar",                 "foo" },
+            { "foo1.2.3.jar",               "foo" },
+
+            { "foo10.jar",                  "foo" },
+            { "foo10.20.jar",               "foo" },
+            { "foo10.20.30.jar",            "foo" },
 
             { "foo-1.jar",                  "foo/1" },
             { "foo-1.2.jar",                "foo/1.2" },
@@ -258,8 +267,8 @@
 
         ModuleDescriptor descriptor = mref.get().descriptor();
         assertTrue(descriptor.provides().size() == 1);
-        assertTrue(descriptor.provides().containsKey(service));
-        ModuleDescriptor.Provides provides = descriptor.provides().get(service);
+        ModuleDescriptor.Provides provides = descriptor.provides().iterator().next();
+        assertEquals(provides.service(), service);
         assertTrue(provides.providers().size() == 1);
         assertTrue(provides.providers().contains((provider)));
     }
@@ -343,17 +352,17 @@
         attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
 
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m1.jar"), man);
+        createDummyJarFile(dir.resolve("m.jar"), man);
 
         ModuleFinder finder = ModuleFinder.of(dir);
 
         Configuration parent = Layer.boot().configuration();
-        Configuration cf = resolve(parent, finder, "m1");
+        Configuration cf = resolve(parent, finder, "m");
 
-        ModuleDescriptor m1 = findDescriptor(cf, "m1");
+        ModuleDescriptor descriptor = findDescriptor(cf, "m");
 
-        assertTrue(m1.mainClass().isPresent());
-        assertEquals(m1.mainClass().get(), mainClass);
+        assertTrue(descriptor.mainClass().isPresent());
+        assertEquals(descriptor.mainClass().get(), mainClass);
     }
 
 
@@ -380,7 +389,7 @@
         attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
 
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m1.jar"), man);
+        createDummyJarFile(dir.resolve("m.jar"), man);
 
         // should throw FindException
         ModuleFinder.of(dir).findAll();
@@ -389,213 +398,213 @@
 
     /**
      * Basic test of a configuration created with automatic modules.
-     *   m1 requires m2*
-     *   m1 requires m3*
-     *   m2*
-     *   m3*
+     *   a requires b*
+     *   a requires c*
+     *   b*
+     *   c*
      */
     public void testConfiguration1() throws Exception {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
-                .requires("m2")
-                .requires("m3")
+            = ModuleDescriptor.module("a")
+                .requires("b")
+                .requires("c")
                 .requires("java.base")
                 .build();
 
-        // m2 and m3 are automatic modules
+        // b and c are automatic modules
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m2.jar"), "p/T.class");
-        createDummyJarFile(dir.resolve("m3.jar"), "q/T.class");
+        createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
+        createDummyJarFile(dir.resolve("c.jar"), "q/T.class");
 
-        // module finder locates m1 and the modules in the directory
+        // module finder locates a and the modules in the directory
         ModuleFinder finder
             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1),
                 ModuleFinder.of(dir));
 
         Configuration parent = Layer.boot().configuration();
-        Configuration cf = resolve(parent, finder, "m1");
+        Configuration cf = resolve(parent, finder, "a");
 
         assertTrue(cf.modules().size() == 3);
-        assertTrue(cf.findModule("m1").isPresent());
-        assertTrue(cf.findModule("m2").isPresent());
-        assertTrue(cf.findModule("m3").isPresent());
+        assertTrue(cf.findModule("a").isPresent());
+        assertTrue(cf.findModule("b").isPresent());
+        assertTrue(cf.findModule("c").isPresent());
 
         ResolvedModule base = cf.findModule("java.base").get();
         assertTrue(base.configuration() == Layer.boot().configuration());
-        ResolvedModule m1 = cf.findModule("m1").get();
-        ResolvedModule m2 = cf.findModule("m2").get();
-        ResolvedModule m3 = cf.findModule("m3").get();
+        ResolvedModule a = cf.findModule("a").get();
+        ResolvedModule b = cf.findModule("b").get();
+        ResolvedModule c = cf.findModule("c").get();
 
-        // m2 && m3 only require java.base
-        assertTrue(m2.reference().descriptor().requires().size() == 1);
-        assertTrue(m3.reference().descriptor().requires().size() == 1);
+        // b && c only require java.base
+        assertTrue(b.reference().descriptor().requires().size() == 1);
+        assertTrue(c.reference().descriptor().requires().size() == 1);
 
         // readability
 
-        assertTrue(m1.reads().size() == 3);
-        assertTrue(m1.reads().contains(base));
-        assertTrue(m1.reads().contains(m2));
-        assertTrue(m1.reads().contains(m3));
+        assertTrue(a.reads().size() == 3);
+        assertTrue(a.reads().contains(base));
+        assertTrue(a.reads().contains(b));
+        assertTrue(a.reads().contains(c));
 
-        assertTrue(m2.reads().contains(m1));
-        assertTrue(m2.reads().contains(m3));
-        testReadAllBootModules(cf, "m2");  // m2 reads all modules in boot layer
+        assertTrue(b.reads().contains(a));
+        assertTrue(b.reads().contains(c));
+        testReadAllBootModules(cf, "b");  // b reads all modules in boot layer
 
-        assertTrue(m3.reads().contains(m1));
-        assertTrue(m3.reads().contains(m2));
-        testReadAllBootModules(cf, "m3");  // m3 reads all modules in boot layer
+        assertTrue(c.reads().contains(a));
+        assertTrue(c.reads().contains(b));
+        testReadAllBootModules(cf, "c");  // c reads all modules in boot layer
 
     }
 
     /**
      * Basic test of a configuration created with automatic modules
-     *   m1 requires m2
-     *   m2 requires m3*
-     *   m3*
-     *   m4*
+     *   a requires b
+     *   b requires c*
+     *   c*
+     *   d*
      */
     public void testInConfiguration2() throws IOException {
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
-                .requires("m2")
+            = ModuleDescriptor.module("a")
+                .requires("b")
                 .requires("java.base")
                 .build();
 
         ModuleDescriptor descriptor2
-            =  new ModuleDescriptor.Builder("m2")
-                .requires("m3")
+            = ModuleDescriptor.module("b")
+                .requires("c")
                 .requires("java.base")
                 .build();
 
-        // m3 and m4 are automatic modules
+        // c and d are automatic modules
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m3.jar"), "p/T.class");
-        createDummyJarFile(dir.resolve("m4.jar"), "q/T.class");
+        createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
+        createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
 
-        // module finder locates m1 and the modules in the directory
+        // module finder locates a and the modules in the directory
         ModuleFinder finder
             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1, descriptor2),
                                    ModuleFinder.of(dir));
 
         Configuration parent = Layer.boot().configuration();
-        Configuration cf = resolve(parent, finder, "m1", "m4");
+        Configuration cf = resolve(parent, finder, "a", "d");
 
         assertTrue(cf.modules().size() == 4);
-        assertTrue(cf.findModule("m1").isPresent());
-        assertTrue(cf.findModule("m2").isPresent());
-        assertTrue(cf.findModule("m3").isPresent());
-        assertTrue(cf.findModule("m4").isPresent());
+        assertTrue(cf.findModule("a").isPresent());
+        assertTrue(cf.findModule("b").isPresent());
+        assertTrue(cf.findModule("c").isPresent());
+        assertTrue(cf.findModule("d").isPresent());
 
-        // m3 && m4 should only require java.base
-        assertTrue(findDescriptor(cf, "m3").requires().size() == 1);
-        assertTrue(findDescriptor(cf, "m4").requires().size() == 1);
+        // c && d should only require java.base
+        assertTrue(findDescriptor(cf, "c").requires().size() == 1);
+        assertTrue(findDescriptor(cf, "d").requires().size() == 1);
 
         // readability
 
         ResolvedModule base = cf.findModule("java.base").get();
         assertTrue(base.configuration() == Layer.boot().configuration());
-        ResolvedModule m1 = cf.findModule("m1").get();
-        ResolvedModule m2 = cf.findModule("m2").get();
-        ResolvedModule m3 = cf.findModule("m3").get();
-        ResolvedModule m4 = cf.findModule("m4").get();
+        ResolvedModule a = cf.findModule("a").get();
+        ResolvedModule b = cf.findModule("b").get();
+        ResolvedModule c = cf.findModule("c").get();
+        ResolvedModule d = cf.findModule("d").get();
 
-        assertTrue(m1.reads().size() == 2);
-        assertTrue(m1.reads().contains(m2));
-        assertTrue(m1.reads().contains(base));
+        assertTrue(a.reads().size() == 2);
+        assertTrue(a.reads().contains(b));
+        assertTrue(a.reads().contains(base));
 
-        assertTrue(m2.reads().size() == 3);
-        assertTrue(m2.reads().contains(m3));
-        assertTrue(m2.reads().contains(m4));
-        assertTrue(m2.reads().contains(base));
+        assertTrue(b.reads().size() == 3);
+        assertTrue(b.reads().contains(c));
+        assertTrue(b.reads().contains(d));
+        assertTrue(b.reads().contains(base));
 
-        assertTrue(m3.reads().contains(m1));
-        assertTrue(m3.reads().contains(m2));
-        assertTrue(m3.reads().contains(m4));
-        testReadAllBootModules(cf, "m3");   // m3 reads all modules in boot layer
+        assertTrue(c.reads().contains(a));
+        assertTrue(c.reads().contains(b));
+        assertTrue(c.reads().contains(d));
+        testReadAllBootModules(cf, "c");   // c reads all modules in boot layer
 
-        assertTrue(m4.reads().contains(m1));
-        assertTrue(m4.reads().contains(m2));
-        assertTrue(m4.reads().contains(m3));
-        testReadAllBootModules(cf, "m4");    // m4 reads all modules in boot layer
+        assertTrue(d.reads().contains(a));
+        assertTrue(d.reads().contains(b));
+        assertTrue(d.reads().contains(c));
+        testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
     }
 
 
     /**
      * Basic test of a configuration created with automatic modules
-     *   m1 requires m2
-     *   m2 requires public m3*
-     *   m3*
-     *   m4*
+     *   a requires b
+     *   b requires transitive c*
+     *   c*
+     *   d*
      */
     public void testInConfiguration3() throws IOException {
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
-                .requires("m2")
+            = ModuleDescriptor.module("a")
+                .requires("b")
                 .requires("java.base")
                 .build();
 
         ModuleDescriptor descriptor2
-            =  new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m3")
+            = ModuleDescriptor.module("b")
+                .requires(Set.of(Modifier.TRANSITIVE), "c")
                 .requires("java.base")
                 .build();
 
-        // m3 and m4 are automatic modules
+        // c and d are automatic modules
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m3.jar"), "p/T.class");
-        createDummyJarFile(dir.resolve("m4.jar"), "q/T.class");
+        createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
+        createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
 
-        // module finder locates m1 and the modules in the directory
+        // module finder locates a and the modules in the directory
         ModuleFinder finder
             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1, descriptor2),
                 ModuleFinder.of(dir));
 
         Configuration parent = Layer.boot().configuration();
-        Configuration cf = resolve(parent, finder, "m1", "m4");
+        Configuration cf = resolve(parent, finder, "a", "d");
 
         assertTrue(cf.modules().size() == 4);
-        assertTrue(cf.findModule("m1").isPresent());
-        assertTrue(cf.findModule("m2").isPresent());
-        assertTrue(cf.findModule("m3").isPresent());
-        assertTrue(cf.findModule("m4").isPresent());
+        assertTrue(cf.findModule("a").isPresent());
+        assertTrue(cf.findModule("b").isPresent());
+        assertTrue(cf.findModule("c").isPresent());
+        assertTrue(cf.findModule("d").isPresent());
 
         ResolvedModule base = cf.findModule("java.base").get();
         assertTrue(base.configuration() == Layer.boot().configuration());
-        ResolvedModule m1 = cf.findModule("m1").get();
-        ResolvedModule m2 = cf.findModule("m2").get();
-        ResolvedModule m3 = cf.findModule("m3").get();
-        ResolvedModule m4 = cf.findModule("m4").get();
+        ResolvedModule a = cf.findModule("a").get();
+        ResolvedModule b = cf.findModule("b").get();
+        ResolvedModule c = cf.findModule("c").get();
+        ResolvedModule d = cf.findModule("d").get();
 
-        // m3 && m4 should only require java.base
-        assertTrue(findDescriptor(cf, "m3").requires().size() == 1);
-        assertTrue(findDescriptor(cf, "m4").requires().size() == 1);
+        // c && d should only require java.base
+        assertTrue(findDescriptor(cf, "c").requires().size() == 1);
+        assertTrue(findDescriptor(cf, "d").requires().size() == 1);
 
         // readability
 
-        assertTrue(m1.reads().size() == 4);
-        assertTrue(m1.reads().contains(m2));
-        assertTrue(m1.reads().contains(m3));
-        assertTrue(m1.reads().contains(m4));
-        assertTrue(m1.reads().contains(base));
+        assertTrue(a.reads().size() == 4);
+        assertTrue(a.reads().contains(b));
+        assertTrue(a.reads().contains(c));
+        assertTrue(a.reads().contains(d));
+        assertTrue(a.reads().contains(base));
 
-        assertTrue(m2.reads().size() == 3);
-        assertTrue(m2.reads().contains(m3));
-        assertTrue(m2.reads().contains(m4));
-        assertTrue(m2.reads().contains(base));
+        assertTrue(b.reads().size() == 3);
+        assertTrue(b.reads().contains(c));
+        assertTrue(b.reads().contains(d));
+        assertTrue(b.reads().contains(base));
 
-        assertTrue(reads(cf, "m2", "m3"));
-        assertTrue(reads(cf, "m2", "m4"));
-        assertTrue(reads(cf, "m2", "java.base"));
+        assertTrue(reads(cf, "b", "c"));
+        assertTrue(reads(cf, "b", "d"));
+        assertTrue(reads(cf, "b", "java.base"));
 
-        assertTrue(m3.reads().contains(m1));
-        assertTrue(m3.reads().contains(m2));
-        assertTrue(m3.reads().contains(m4));
-        testReadAllBootModules(cf, "m3");   // m3 reads all modules in boot layer
+        assertTrue(c.reads().contains(a));
+        assertTrue(c.reads().contains(b));
+        assertTrue(c.reads().contains(d));
+        testReadAllBootModules(cf, "c");   // c reads all modules in boot layer
 
-        assertTrue(m4.reads().contains(m1));
-        assertTrue(m4.reads().contains(m2));
-        assertTrue(m4.reads().contains(m3));
-        testReadAllBootModules(cf, "m4");    // m4 reads all modules in boot layer
+        assertTrue(d.reads().contains(a));
+        assertTrue(d.reads().contains(b));
+        assertTrue(d.reads().contains(c));
+        testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
     }
 
 
@@ -604,23 +613,23 @@
      */
     public void testInLayer() throws IOException {
         ModuleDescriptor descriptor
-            =  new ModuleDescriptor.Builder("m1")
-                .requires("m2")
-                .requires("m3")
+            = ModuleDescriptor.module("a")
+                .requires("b")
+                .requires("c")
                 .build();
 
-        // m2 and m3 are simple JAR files
+        // b and c are simple JAR files
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m2.jar"), "p/T.class");
-        createDummyJarFile(dir.resolve("m3.jar"), "q/T2.class");
+        createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
+        createDummyJarFile(dir.resolve("c.jar"), "q/T2.class");
 
-        // module finder locates m1 and the modules in the directory
+        // module finder locates a and the modules in the directory
         ModuleFinder finder
             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
                 ModuleFinder.of(dir));
 
         Configuration parent = Layer.boot().configuration();
-        Configuration cf = resolve(parent, finder, "m1");
+        Configuration cf = resolve(parent, finder, "a");
         assertTrue(cf.modules().size() == 3);
 
         // each module gets its own loader
@@ -629,15 +638,15 @@
         // an unnamed module
         Module unnamed = (new ClassLoader() { }).getUnnamedModule();
 
-        Module m2 = layer.findModule("m2").get();
-        assertTrue(m2.isNamed());
-        assertTrue(m2.canRead(unnamed));
-        testsReadsAll(m2, layer);
+        Module b = layer.findModule("b").get();
+        assertTrue(b.isNamed());
+        assertTrue(b.canRead(unnamed));
+        testsReadsAll(b, layer);
 
-        Module m3 = layer.findModule("m3").get();
-        assertTrue(m3.isNamed());
-        assertTrue(m2.canRead(unnamed));
-        testsReadsAll(m3, layer);
+        Module c = layer.findModule("c").get();
+        assertTrue(c.isNamed());
+        assertTrue(b.canRead(unnamed));
+        testsReadsAll(c, layer);
     }
 
 
@@ -646,19 +655,19 @@
      */
     public void testMisc() throws IOException {
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        Path m1_jar = createDummyJarFile(dir.resolve("m1.jar"), "p/T.class");
+        Path m_jar = createDummyJarFile(dir.resolve("m.jar"), "p/T.class");
 
-        ModuleFinder finder = ModuleFinder.of(m1_jar);
+        ModuleFinder finder = ModuleFinder.of(m_jar);
 
-        assertTrue(finder.find("m1").isPresent());
-        ModuleDescriptor m1 = finder.find("m1").get().descriptor();
+        assertTrue(finder.find("m").isPresent());
+        ModuleDescriptor m = finder.find("m").get().descriptor();
 
         // test miscellaneous methods
-        assertTrue(m1.isAutomatic());
-        assertFalse(m1.isSynthetic());
-        assertFalse(m1.osName().isPresent());
-        assertFalse(m1.osArch().isPresent());
-        assertFalse(m1.osVersion().isPresent());
+        assertTrue(m.isAutomatic());
+        assertFalse(m.isSynthetic());
+        assertFalse(m.osName().isPresent());
+        assertFalse(m.osArch().isPresent());
+        assertFalse(m.osVersion().isPresent());
     }
 
 
@@ -703,17 +712,15 @@
      * and its parent Layers.
      */
     static void testsReadsAll(Module m, Layer layer) {
-        while (layer != Layer.empty()) {
+        // check that m reads all modules in the layer
+        layer.configuration().modules().stream()
+            .map(ResolvedModule::name)
+            .map(layer::findModule)
+            .map(Optional::get)
+            .forEach(other -> assertTrue(m.canRead(other)));
 
-            // check that m reads all module in the layer
-            layer.configuration().modules().stream()
-                .map(ResolvedModule::name)
-                .map(layer::findModule)
-                .map(Optional::get)
-                .forEach(m2 -> assertTrue(m.canRead(m2)));
-
-            layer = layer.parent().get();
-        }
+        // also check parent layers
+        layer.parents().forEach(l -> testsReadsAll(m, l));
     }
 
     /**
@@ -721,11 +728,11 @@
      * that reads module mn2.
      */
     static boolean reads(Configuration cf, String mn1, String mn2) {
-        Optional<ResolvedModule> om1 = cf.findModule(mn1);
-        if (!om1.isPresent())
+        Optional<ResolvedModule> om = cf.findModule(mn1);
+        if (!om.isPresent())
             return false;
 
-        return om1.get().reads().stream()
+        return om.get().reads().stream()
                 .map(ResolvedModule::name)
                 .anyMatch(mn2::equals);
     }
@@ -757,7 +764,7 @@
      * in the resulting JAR file.
      */
     static Path createDummyJarFile(Path jarfile, String... entries)
-        throws IOException
+            throws IOException
     {
         return createDummyJarFile(jarfile, null, entries);
     }
diff --git a/jdk/test/java/lang/module/ConfigurationTest.java b/jdk/test/java/lang/module/ConfigurationTest.java
index a739875..7ae8672 100644
--- a/jdk/test/java/lang/module/ConfigurationTest.java
+++ b/jdk/test/java/lang/module/ConfigurationTest.java
@@ -31,11 +31,13 @@
 
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ResolutionException;
 import java.lang.module.ResolvedModule;
 import java.lang.reflect.Layer;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 
@@ -53,17 +55,17 @@
      */
     public void testBasic() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("m2")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m3")
                 .build();
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .build();
 
         ModuleFinder finder
@@ -77,7 +79,8 @@
         assertTrue(cf.findModule("m2").isPresent());
         assertTrue(cf.findModule("m3").isPresent());
 
-        assertTrue(cf.parent().get() == Configuration.empty());
+        assertTrue(cf.parents().size() == 1);
+        assertTrue(cf.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf.findModule("m1").get();
         ResolvedModule m2 = cf.findModule("m2").get();
@@ -102,23 +105,23 @@
 
 
     /**
-     * Basic test of "requires public":
-     *     m1 requires m2, m2 requires public m3
+     * Basic test of "requires transitive":
+     *     m1 requires m2, m2 requires transitive m3
      */
-    public void testRequiresPublic1() {
-        // m1 requires m2, m2 requires public m3
+    public void testRequiresTransitive1() {
+        // m1 requires m2, m2 requires transitive m3
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("m2")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m3")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m3")
                 .build();
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .build();
 
         ModuleFinder finder
@@ -132,7 +135,8 @@
         assertTrue(cf.findModule("m2").isPresent());
         assertTrue(cf.findModule("m3").isPresent());
 
-        assertTrue(cf.parent().get() == Configuration.empty());
+        assertTrue(cf.parents().size() == 1);
+        assertTrue(cf.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf.findModule("m1").get();
         ResolvedModule m2 = cf.findModule("m2").get();
@@ -153,23 +157,23 @@
 
 
     /**
-     * Basic test of "requires public" with configurations.
+     * Basic test of "requires transitive" with configurations.
      *
      * The test consists of three configurations:
-     * - Configuration cf1: m1, m2 requires public m1
+     * - Configuration cf1: m1, m2 requires transitive m1
      * - Configuration cf2: m3 requires m2
      */
-    public void testRequiresPublic2() {
+    public void testRequiresTransitive2() {
 
-        // cf1: m1 and m2, m2 requires public m1
+        // cf1: m1 and m2, m2 requires transitive m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
@@ -179,7 +183,8 @@
         assertTrue(cf1.modules().size() == 2);
         assertTrue(cf1.findModule("m1").isPresent());
         assertTrue(cf1.findModule("m2").isPresent());
-        assertTrue(cf1.parent().get() == Configuration.empty());
+        assertTrue(cf1.parents().size() == 1);
+        assertTrue(cf1.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf1.findModule("m1").get();
         ResolvedModule m2 = cf1.findModule("m2").get();
@@ -192,7 +197,7 @@
         // cf2: m3, m3 requires m2
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -204,7 +209,8 @@
         assertTrue(cf2.findModule("m1").isPresent());  // in parent
         assertTrue(cf2.findModule("m2").isPresent());  // in parent
         assertTrue(cf2.findModule("m3").isPresent());
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
 
         ResolvedModule m3 = cf2.findModule("m3").get();
         assertTrue(m3.configuration() == cf2);
@@ -215,18 +221,18 @@
 
 
     /**
-     * Basic test of "requires public" with configurations.
+     * Basic test of "requires transitive" with configurations.
      *
      * The test consists of three configurations:
      * - Configuration cf1: m1
-     * - Configuration cf2: m2 requires public m1, m3 requires m2
+     * - Configuration cf2: m2 requires transitive m1, m3 requires m2
      */
-    public void testRequiresPublic3() {
+    public void testRequiresTransitive3() {
 
         // cf1: m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
@@ -235,21 +241,22 @@
 
         assertTrue(cf1.modules().size() == 1);
         assertTrue(cf1.findModule("m1").isPresent());
-        assertTrue(cf1.parent().get() == Configuration.empty());
+        assertTrue(cf1.parents().size() == 1);
+        assertTrue(cf1.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf1.findModule("m1").get();
         assertTrue(m1.reads().size() == 0);
 
 
-        // cf2: m2, m3: m2 requires public m1, m3 requires m2
+        // cf2: m2, m3: m2 requires transitive m1, m3 requires m2
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -261,7 +268,8 @@
         assertTrue(cf2.findModule("m1").isPresent());   // in parent
         assertTrue(cf2.findModule("m2").isPresent());
         assertTrue(cf2.findModule("m3").isPresent());
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
 
         ResolvedModule m2 = cf2.findModule("m2").get();
         ResolvedModule m3 = cf2.findModule("m3").get();
@@ -278,19 +286,19 @@
 
 
     /**
-     * Basic test of "requires public" with configurations.
+     * Basic test of "requires transitive" with configurations.
      *
      * The test consists of three configurations:
      * - Configuration cf1: m1
-     * - Configuration cf2: m2 requires public m1
+     * - Configuration cf2: m2 requires transitive m1
      * - Configuraiton cf3: m3 requires m2
      */
-    public void testRequiresPublic4() {
+    public void testRequiresTransitive4() {
 
         // cf1: m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
@@ -299,17 +307,18 @@
 
         assertTrue(cf1.modules().size() == 1);
         assertTrue(cf1.findModule("m1").isPresent());
-        assertTrue(cf1.parent().get() == Configuration.empty());
+        assertTrue(cf1.parents().size() == 1);
+        assertTrue(cf1.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf1.findModule("m1").get();
         assertTrue(m1.reads().size() == 0);
 
 
-        // cf2: m2 requires public m1
+        // cf2: m2 requires transitive m1
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
@@ -319,7 +328,8 @@
         assertTrue(cf2.modules().size() == 1);
         assertTrue(cf2.findModule("m1").isPresent());  // in parent
         assertTrue(cf2.findModule("m2").isPresent());
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
 
         ResolvedModule m2 = cf2.findModule("m2").get();
 
@@ -331,7 +341,7 @@
         // cf3: m3 requires m2
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -343,7 +353,8 @@
         assertTrue(cf3.findModule("m1").isPresent());  // in parent
         assertTrue(cf3.findModule("m2").isPresent());  // in parent
         assertTrue(cf3.findModule("m3").isPresent());
-        assertTrue(cf3.parent().get() == cf2);
+        assertTrue(cf3.parents().size() == 1);
+        assertTrue(cf3.parents().get(0) == cf2);
 
         ResolvedModule m3 = cf3.findModule("m3").get();
 
@@ -355,23 +366,23 @@
 
 
     /**
-     * Basic test of "requires public" with configurations.
+     * Basic test of "requires transitive" with configurations.
      *
      * The test consists of two configurations:
-     * - Configuration cf1: m1, m2 requires public m1
-     * - Configuration cf2: m3 requires public m2, m4 requires m3
+     * - Configuration cf1: m1, m2 requires transitive m1
+     * - Configuration cf2: m3 requires transitive m2, m4 requires m3
      */
-    public void testRequiresPublic5() {
+    public void testRequiresTransitive5() {
 
-        // cf1: m1, m2 requires public m1
+        // cf1: m1, m2 requires transitive m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
@@ -381,7 +392,8 @@
         assertTrue(cf1.modules().size() == 2);
         assertTrue(cf1.findModule("m1").isPresent());
         assertTrue(cf1.findModule("m2").isPresent());
-        assertTrue(cf1.parent().get() == Configuration.empty());
+        assertTrue(cf1.parents().size() == 1);
+        assertTrue(cf1.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf1.findModule("m1").get();
         ResolvedModule m2 = cf1.findModule("m2").get();
@@ -394,15 +406,15 @@
         assertTrue(m2.reads().contains(m1));
 
 
-        // cf2: m3 requires public m2, m4 requires m3
+        // cf2: m3 requires transitive m2, m4 requires m3
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
-                .requires(Modifier.PUBLIC, "m2")
+            = ModuleDescriptor.module("m3")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m2")
                 .build();
 
         ModuleDescriptor descriptor4
-            = new ModuleDescriptor.Builder("m4")
+            = ModuleDescriptor.module("m4")
                 .requires("m3")
                 .build();
 
@@ -416,7 +428,8 @@
         assertTrue(cf2.findModule("m2").isPresent());   // in parent
         assertTrue(cf2.findModule("m3").isPresent());
         assertTrue(cf2.findModule("m4").isPresent());
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
 
         ResolvedModule m3 = cf2.findModule("m3").get();
         ResolvedModule m4 = cf2.findModule("m4").get();
@@ -435,6 +448,362 @@
 
 
     /**
+     * Basic test of "requires transitive" with configurations.
+     *
+     * The test consists of three configurations:
+     * - Configuration cf1: m1, m2 requires transitive m1
+     * - Configuration cf2: m1, m3 requires transitive m1
+     * - Configuration cf3(cf1,cf2): m4 requires m2, m3
+     */
+    public void testRequiresTransitive6() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
+                .build();
+
+        ModuleDescriptor descriptor4
+            = ModuleDescriptor.module("m4")
+                .requires("m2")
+                .requires("m3")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
+        Configuration cf1 = resolveRequires(finder1, "m2");
+        assertTrue(cf1.modules().size() == 2);
+        assertTrue(cf1.findModule("m1").isPresent());
+        assertTrue(cf1.findModule("m2").isPresent());
+        assertTrue(cf1.parents().size() == 1);
+        assertTrue(cf1.parents().get(0) == Configuration.empty());
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3);
+        Configuration cf2 = resolveRequires(finder2, "m3");
+        assertTrue(cf2.modules().size() == 2);
+        assertTrue(cf2.findModule("m3").isPresent());
+        assertTrue(cf2.findModule("m1").isPresent());
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == Configuration.empty());
+
+        ModuleFinder finder3 = ModuleUtils.finderOf(descriptor4);
+        Configuration cf3 = Configuration.resolveRequires(finder3,
+                List.of(cf1, cf2),
+                ModuleFinder.of(),
+                Set.of("m4"));
+        assertTrue(cf3.modules().size() == 1);
+        assertTrue(cf3.findModule("m4").isPresent());
+
+        ResolvedModule m1_l = cf1.findModule("m1").get();
+        ResolvedModule m1_r = cf2.findModule("m1").get();
+        ResolvedModule m2 = cf1.findModule("m2").get();
+        ResolvedModule m3 = cf2.findModule("m3").get();
+        ResolvedModule m4 = cf3.findModule("m4").get();
+        assertTrue(m4.configuration() == cf3);
+
+        assertTrue(m4.reads().size() == 4);
+        assertTrue(m4.reads().contains(m1_l));
+        assertTrue(m4.reads().contains(m1_r));
+        assertTrue(m4.reads().contains(m2));
+        assertTrue(m4.reads().contains(m3));
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     *     m1 requires static m2
+     *     m2 is not observable
+     *     resolve m1
+     */
+    public void testRequiresStatic1() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .requires(Set.of(Requires.Modifier.STATIC), "m2")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 1);
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        assertTrue(m1.reads().size() == 0);
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     *     m1 requires static m2
+     *     m2
+     *     resolve m1
+     */
+    public void testRequiresStatic2() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .requires(Set.of(Requires.Modifier.STATIC), "m2")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 1);
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        assertTrue(m1.reads().size() == 0);
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     *     m1 requires static m2
+     *     m2
+     *     resolve m1, m2
+     */
+    public void testRequiresStatic3() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .requires(Set.of(Requires.Modifier.STATIC), "m2")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf = resolveRequires(finder, "m1", "m2");
+
+        assertTrue(cf.modules().size() == 2);
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+
+        assertTrue(m1.reads().size() == 1);
+        assertTrue(m1.reads().contains(m2));
+
+        assertTrue(m2.reads().size() == 0);
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     *     m1 requires m2, m3
+     *     m2 requires static m2
+     *     m3
+     */
+    public void testRequiresStatic4() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .requires("m2")
+                .requires("m3")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.STATIC), "m3")
+                .build();
+
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .build();
+
+        ModuleFinder finder
+                = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
+
+        Configuration cf = resolveRequires(finder, "m1");
+
+        assertTrue(cf.modules().size() == 3);
+
+        ResolvedModule m1 = cf.findModule("m1").get();
+        ResolvedModule m2 = cf.findModule("m2").get();
+        ResolvedModule m3 = cf.findModule("m3").get();
+
+        assertTrue(m1.reads().size() == 2);
+        assertTrue(m1.reads().contains(m2));
+        assertTrue(m1.reads().contains(m3));
+
+        assertTrue(m2.reads().size() == 1);
+        assertTrue(m2.reads().contains(m3));
+
+        assertTrue(m3.reads().size() == 0);
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     * The test consists of three configurations:
+     * - Configuration cf1: m1, m2
+     * - Configuration cf2: m3 requires m1, requires static m2
+     */
+    public void testRequiresStatic5() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
+
+        Configuration cf1 = resolveRequires(finder1, "m1", "m2");
+
+        assertTrue(cf1.modules().size() == 2);
+        assertTrue(cf1.findModule("m1").isPresent());
+        assertTrue(cf1.findModule("m2").isPresent());
+
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .requires("m1")
+                .requires(Set.of(Requires.Modifier.STATIC), "m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m3").isPresent());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        ResolvedModule m2 = cf1.findModule("m2").get();
+        ResolvedModule m3 = cf2.findModule("m3").get();
+
+        assertTrue(m3.reads().size() == 2);
+        assertTrue(m3.reads().contains(m1));
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     * The test consists of three configurations:
+     * - Configuration cf1: m1
+     * - Configuration cf2: m3 requires m1, requires static m2
+     */
+    public void testRequiresStatic6() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
+
+        Configuration cf1 = resolveRequires(finder1, "m1");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .requires("m1")
+                .requires(Set.of(Requires.Modifier.STATIC), "m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m3").isPresent());
+
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        ResolvedModule m3 = cf2.findModule("m3").get();
+
+        assertTrue(m3.reads().size() == 1);
+        assertTrue(m3.reads().contains(m1));
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     *     (m1 not observable)
+     *     m2 requires transitive static m1
+     *     m3 requires m2
+     */
+    public void testRequiresStatic7() {
+        ModuleDescriptor descriptor1 = null;  // not observable
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE,
+                                Requires.Modifier.STATIC),
+                         "m1")
+                .build();
+
+        ModuleDescriptor descriptor3
+                = ModuleDescriptor.module("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor2, descriptor3);
+
+        Configuration cf = resolveRequires(finder, "m3");
+
+        assertTrue(cf.modules().size() == 2);
+        assertTrue(cf.findModule("m2").isPresent());
+        assertTrue(cf.findModule("m3").isPresent());
+        ResolvedModule m2 = cf.findModule("m2").get();
+        ResolvedModule m3 = cf.findModule("m3").get();
+        assertTrue(m2.reads().isEmpty());
+        assertTrue(m3.reads().size() == 1);
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
+     * Basic test of "requires static":
+     * - Configuration cf1: m2 requires transitive static m1
+     * - Configuration cf2: m3 requires m2
+     */
+    public void testRequiresStatic8() {
+        ModuleDescriptor descriptor1 = null;  // not observable
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE,
+                                Requires.Modifier.STATIC),
+                        "m1")
+                .build();
+
+        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor2);
+
+        Configuration cf1 = resolveRequires(finder1, "m2");
+
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m2").isPresent());
+        ResolvedModule m2 = cf1.findModule("m2").get();
+        assertTrue(m2.reads().isEmpty());
+
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .requires("m2")
+                .build();
+
+        ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
+
+        Configuration cf2 = resolveRequires(cf1, finder2, "m3");
+
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m3").isPresent());
+        ResolvedModule m3 = cf2.findModule("m3").get();
+        assertTrue(m3.reads().size() == 1);
+        assertTrue(m3.reads().contains(m2));
+    }
+
+
+    /**
      * Basic test of binding services
      *     m1 uses p.S
      *     m2 provides p.S
@@ -442,15 +811,15 @@
     public void testServiceBinding1() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -461,7 +830,8 @@
         assertTrue(cf.modules().size() == 2);
         assertTrue(cf.findModule("m1").isPresent());
         assertTrue(cf.findModule("m2").isPresent());
-        assertTrue(cf.parent().get() == Configuration.empty());
+        assertTrue(cf.parents().size() == 1);
+        assertTrue(cf.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf.findModule("m1").get();
         ResolvedModule m2 = cf.findModule("m2").get();
@@ -484,23 +854,23 @@
     public void testServiceBinding2() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
                 .uses("p.S2")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S1", "q.Service1Impl")
                 .build();
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m1")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S2", "q.Service2Impl")
                 .build();
 
@@ -513,7 +883,8 @@
         assertTrue(cf.findModule("m1").isPresent());
         assertTrue(cf.findModule("m2").isPresent());
         assertTrue(cf.findModule("m3").isPresent());
-        assertTrue(cf.parent().get() == Configuration.empty());
+        assertTrue(cf.parents().size() == 1);
+        assertTrue(cf.parents().get(0) == Configuration.empty());
 
         ResolvedModule m1 = cf.findModule("m1").get();
         ResolvedModule m2 = cf.findModule("m2").get();
@@ -542,7 +913,7 @@
     public void testServiceBindingWithConfigurations1() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S")
                 .build();
@@ -555,9 +926,9 @@
         assertTrue(cf1.findModule("m1").isPresent());
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -565,7 +936,9 @@
 
         Configuration cf2 = resolveRequiresAndUses(cf1, finder2); // no roots
 
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
+
         assertTrue(cf2.modules().size() == 1);
         assertTrue(cf2.findModule("m2").isPresent());
 
@@ -589,17 +962,17 @@
     public void testServiceBindingWithConfigurations2() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S")
-                .conceals("p1")
+                .contains("p1")
                 .provides("p.S", "p1.ServiceImpl")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
-                .conceals("p2")
+                .contains("p2")
                 .provides("p.S", "p2.ServiceImpl")
                 .build();
 
@@ -613,16 +986,16 @@
 
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m1")
-                .conceals("p3")
+                .contains("p3")
                 .provides("p.S", "p3.ServiceImpl")
                 .build();
 
         ModuleDescriptor descriptor4
-            = new ModuleDescriptor.Builder("m4")
+            = ModuleDescriptor.module("m4")
                 .requires("m1")
-                .conceals("p4")
+                .contains("p4")
                 .provides("p.S", "p4.ServiceImpl")
                 .build();
 
@@ -630,7 +1003,9 @@
 
         Configuration cf2 = resolveRequiresAndUses(cf1, finder2); // no roots
 
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
+
         assertTrue(cf2.modules().size() == 2);
         assertTrue(cf2.findModule("m3").isPresent());
         assertTrue(cf2.findModule("m4").isPresent());
@@ -663,15 +1038,15 @@
     public void testServiceBindingWithConfigurations3() {
 
         ModuleDescriptor service
-            = new ModuleDescriptor.Builder("s")
+            = ModuleDescriptor.module("s")
                 .exports("p")
                 .build();
 
         ModuleDescriptor provider_v1
-            = new ModuleDescriptor.Builder("p")
+            = ModuleDescriptor.module("p")
                 .version("1.0")
                 .requires("s")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -689,16 +1064,16 @@
 
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("s")
                 .uses("p.S")
                 .build();
 
         ModuleDescriptor provider_v2
-            = new ModuleDescriptor.Builder("p")
+            = ModuleDescriptor.module("p")
                 .version("2.0")
                 .requires("s")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -709,7 +1084,8 @@
 
         Configuration cf2 = resolveRequiresAndUses(cf1, finder2, "m1");
 
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
         assertTrue(cf2.modules().size() == 2);
 
         // p should be found in cf2
@@ -723,7 +1099,8 @@
 
         cf2 = resolveRequiresAndUses(cf1, ModuleFinder.of(), finder2, "m1");
 
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
         assertTrue(cf2.modules().size() == 1);
 
         // p should be found in cf1
@@ -741,17 +1118,17 @@
     public void testWithTwoFinders1() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("m2")
                 .build();
 
         ModuleDescriptor descriptor2_v1
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .version("1.0")
                 .build();
 
         ModuleDescriptor descriptor2_v2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .version("2.0")
                 .build();
 
@@ -781,22 +1158,22 @@
     public void testWithTwoFinders2() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S")
                 .build();
 
         ModuleDescriptor descriptor2_v1
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
         ModuleDescriptor descriptor2_v2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -824,7 +1201,7 @@
     public void testResolvedInParent1() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
@@ -847,7 +1224,7 @@
     public void testResolvedInParent2() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
@@ -859,7 +1236,7 @@
 
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
                 .build();
 
@@ -880,12 +1257,221 @@
 
 
     /**
-     * Basic test of using the beforeFinder to override a module in the parent
+     * Basic test of resolving a module that depends on modules in two parent
+     * configurations.
+     *
+     * The test consists of three configurations:
+     * - Configuration cf1: m1
+     * - Configuration cf2: m2
+     * - Configuration cf3(cf1,cf2): m3 requires m1, m2
+     */
+    public void testResolvedInMultipleParents1() {
+
+        // Configuration cf1: m1
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module("m1").build();
+        Configuration cf1 = resolveRequires(ModuleUtils.finderOf(descriptor1), "m1");
+        assertEquals(cf1.parents(), List.of(Configuration.empty()));
+        assertTrue(cf1.findModule("m1").isPresent());
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        assertTrue(m1.configuration() == cf1);
+
+        // Configuration cf2: m2
+        ModuleDescriptor descriptor2 = ModuleDescriptor.module("m2").build();
+        Configuration cf2 = resolveRequires(ModuleUtils.finderOf(descriptor2), "m2");
+        assertEquals(cf2.parents(), List.of(Configuration.empty()));
+        assertTrue(cf2.findModule("m2").isPresent());
+        ResolvedModule m2 = cf2.findModule("m2").get();
+        assertTrue(m2.configuration() == cf2);
+
+        // Configuration cf3(cf1,cf2): m3 requires m1 and m2
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .requires("m1")
+                .requires("m2")
+                .build();
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor3);
+        Configuration cf3 = Configuration.resolveRequires(
+                finder,
+                List.of(cf1, cf2),  // parents
+                ModuleFinder.of(),
+                Set.of("m3"));
+        assertEquals(cf3.parents(), List.of(cf1, cf2));
+        assertTrue(cf3.findModule("m3").isPresent());
+        ResolvedModule m3 = cf3.findModule("m3").get();
+        assertTrue(m3.configuration() == cf3);
+
+        // check readability
+        assertTrue(m1.reads().isEmpty());
+        assertTrue(m2.reads().isEmpty());
+        assertEquals(m3.reads(), Set.of(m1, m2));
+    }
+
+
+    /**
+     * Basic test of resolving a module that depends on modules in three parent
+     * configurations arranged in a diamond (two direct parents).
+     *
+     * The test consists of four configurations:
+     * - Configuration cf1: m1
+     * - Configuration cf2(cf1): m2 requires m1
+     * - Configuration cf3(cf3): m3 requires m1
+     * - Configuration cf4(cf2,cf3): m4 requires m1,m2,m3
+     */
+    public void testResolvedInMultipleParents2() {
+        // Configuration cf1: m1
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module("m1").build();
+        Configuration cf1 = resolveRequires(ModuleUtils.finderOf(descriptor1), "m1");
+        assertEquals(cf1.parents(), List.of(Configuration.empty()));
+        assertTrue(cf1.findModule("m1").isPresent());
+        ResolvedModule m1 = cf1.findModule("m1").get();
+        assertTrue(m1.configuration() == cf1);
+
+        // Configuration cf2(cf1): m2 requires m1
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .requires("m1")
+                .build();
+        Configuration cf2 = Configuration.resolveRequires(
+                ModuleUtils.finderOf(descriptor2),
+                List.of(cf1),  // parents
+                ModuleFinder.of(),
+                Set.of("m2"));
+        assertEquals(cf2.parents(), List.of(cf1));
+        assertTrue(cf2.findModule("m2").isPresent());
+        ResolvedModule m2 = cf2.findModule("m2").get();
+        assertTrue(m2.configuration() == cf2);
+
+        // Configuration cf3(cf1): m3 requires m1
+        ModuleDescriptor descriptor3
+            = ModuleDescriptor.module("m3")
+                .requires("m1")
+                .build();
+        Configuration cf3 = Configuration.resolveRequires(
+                ModuleUtils.finderOf(descriptor3),
+                List.of(cf1),  // parents
+                ModuleFinder.of(),
+                Set.of("m3"));
+        assertEquals(cf3.parents(), List.of(cf1));
+        assertTrue(cf3.findModule("m3").isPresent());
+        ResolvedModule m3 = cf3.findModule("m3").get();
+        assertTrue(m3.configuration() == cf3);
+
+        // Configuration cf4(cf2,cf3): m4 requires m1,m2,m3
+        ModuleDescriptor descriptor4
+            = ModuleDescriptor.module("m4")
+                .requires("m1")
+                .requires("m2")
+                .requires("m3")
+                .build();
+        Configuration cf4 = Configuration.resolveRequires(
+                ModuleUtils.finderOf(descriptor4),
+                List.of(cf2, cf3),  // parents
+                ModuleFinder.of(),
+                Set.of("m4"));
+        assertEquals(cf4.parents(), List.of(cf2, cf3));
+        assertTrue(cf4.findModule("m4").isPresent());
+        ResolvedModule m4 = cf4.findModule("m4").get();
+        assertTrue(m4.configuration() == cf4);
+
+        // check readability
+        assertTrue(m1.reads().isEmpty());
+        assertEquals(m2.reads(), Set.of(m1));
+        assertEquals(m3.reads(), Set.of(m1));
+        assertEquals(m4.reads(), Set.of(m1, m2, m3));
+    }
+
+
+    /**
+     * Basic test of resolving a module that depends on modules in three parent
+     * configurations arranged in a diamond (two direct parents).
+     *
+     * The test consists of four configurations:
+     * - Configuration cf1: m1@1
+     * - Configuration cf2: m1@2, m2@2
+     * - Configuration cf3: m1@3, m2@3, m3@3
+     * - Configuration cf4(cf1,cf2,cf3): m4 requires m1,m2,m3
+     */
+    public void testResolvedInMultipleParents3() {
+        ModuleDescriptor descriptor1, descriptor2, descriptor3;
+
+        // Configuration cf1: m1@1
+        descriptor1 = ModuleDescriptor.module("m1").version("1").build();
+        Configuration cf1 = resolveRequires(ModuleUtils.finderOf(descriptor1), "m1");
+        assertEquals(cf1.parents(), List.of(Configuration.empty()));
+
+        // Configuration cf2: m1@2, m2@2
+        descriptor1 = ModuleDescriptor.module("m1").version("2").build();
+        descriptor2 = ModuleDescriptor.module("m2").version("2").build();
+        Configuration cf2 = resolveRequires(
+                ModuleUtils.finderOf(descriptor1, descriptor2),
+                "m1", "m2");
+        assertEquals(cf2.parents(), List.of(Configuration.empty()));
+
+        // Configuration cf3: m1@3, m2@3, m3@3
+        descriptor1 = ModuleDescriptor.module("m1").version("3").build();
+        descriptor2 = ModuleDescriptor.module("m2").version("3").build();
+        descriptor3 = ModuleDescriptor.module("m3").version("3").build();
+        Configuration cf3 = resolveRequires(
+                ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3),
+                "m1", "m2", "m3");
+        assertEquals(cf3.parents(), List.of(Configuration.empty()));
+
+        // Configuration cf4(cf1,cf2,cf3): m4 requires m1,m2,m3
+        ModuleDescriptor descriptor4
+                = ModuleDescriptor.module("m4")
+                .requires("m1")
+                .requires("m2")
+                .requires("m3")
+                .build();
+        Configuration cf4 = Configuration.resolveRequires(
+                ModuleUtils.finderOf(descriptor4),
+                List.of(cf1, cf2, cf3),  // parents
+                ModuleFinder.of(),
+                Set.of("m4"));
+        assertEquals(cf4.parents(), List.of(cf1, cf2, cf3));
+
+        assertTrue(cf1.findModule("m1").isPresent());
+        assertTrue(cf2.findModule("m1").isPresent());
+        assertTrue(cf2.findModule("m2").isPresent());
+        assertTrue(cf3.findModule("m1").isPresent());
+        assertTrue(cf3.findModule("m2").isPresent());
+        assertTrue(cf3.findModule("m3").isPresent());
+        assertTrue(cf4.findModule("m4").isPresent());
+
+        ResolvedModule m1_1 = cf1.findModule("m1").get();
+        ResolvedModule m1_2 = cf2.findModule("m1").get();
+        ResolvedModule m2_2 = cf2.findModule("m2").get();
+        ResolvedModule m1_3 = cf3.findModule("m1").get();
+        ResolvedModule m2_3 = cf3.findModule("m2").get();
+        ResolvedModule m3_3 = cf3.findModule("m3").get();
+        ResolvedModule m4   = cf4.findModule("m4").get();
+
+        assertTrue(m1_1.configuration() == cf1);
+        assertTrue(m1_2.configuration() == cf2);
+        assertTrue(m2_2.configuration() == cf2);
+        assertTrue(m1_3.configuration() == cf3);
+        assertTrue(m2_3.configuration() == cf3);
+        assertTrue(m3_3.configuration() == cf3);
+        assertTrue(m4.configuration() == cf4);
+
+        // check readability
+        assertTrue(m1_1.reads().isEmpty());
+        assertTrue(m1_2.reads().isEmpty());
+        assertTrue(m2_2.reads().isEmpty());
+        assertTrue(m1_3.reads().isEmpty());
+        assertTrue(m2_3.reads().isEmpty());
+        assertTrue(m3_3.reads().isEmpty());
+        assertEquals(m4.reads(), Set.of(m1_1, m2_2, m3_3));
+    }
+
+
+    /**
+     * Basic test of using the beforeFinder to override a module in a parent
      * configuration.
      */
     public void testOverriding1() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
@@ -899,6 +1485,39 @@
         assertTrue(cf2.findModule("m1").isPresent());
     }
 
+    /**
+     * Basic test of using the beforeFinder to override a module in a parent
+     * configuration.
+     */
+    public void testOverriding2() {
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module("m1").build();
+        Configuration cf1 = resolveRequires(ModuleUtils.finderOf(descriptor1), "m1");
+        assertTrue(cf1.modules().size() == 1);
+        assertTrue(cf1.findModule("m1").isPresent());
+
+        ModuleDescriptor descriptor2 = ModuleDescriptor.module("m2").build();
+        Configuration cf2 = resolveRequires(ModuleUtils.finderOf(descriptor2), "m2");
+        assertTrue(cf2.modules().size() == 1);
+        assertTrue(cf2.findModule("m2").isPresent());
+
+        ModuleDescriptor descriptor3 = ModuleDescriptor.module("m3").build();
+        Configuration cf3 = resolveRequires(ModuleUtils.finderOf(descriptor3), "m3");
+        assertTrue(cf3.modules().size() == 1);
+        assertTrue(cf3.findModule("m3").isPresent());
+
+        // override m2, m1 and m3 should be found in parent configurations
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor2);
+        Configuration cf4 = Configuration.resolveRequires(
+                finder,
+                List.of(cf1, cf2, cf3),
+                ModuleFinder.of(),
+                Set.of("m1", "m2", "m3"));
+        assertTrue(cf4.modules().size() == 1);
+        assertTrue(cf4.findModule("m2").isPresent());
+        ResolvedModule m2 = cf4.findModule("m2").get();
+        assertTrue(m2.configuration() == cf4);
+    }
+
 
     /**
      * Basic test of using the beforeFinder to override a module in the parent
@@ -906,18 +1525,18 @@
      * module in the parent is read.
      *
      * The test consists of two configurations:
-     * - Configuration cf1: m1, m2 requires public m1
+     * - Configuration cf1: m1, m2 requires transitive m1
      * - Configuration cf2: m1, m3 requires m2
      */
-    public void testOverriding2() {
+    public void testOverriding3() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
@@ -931,7 +1550,7 @@
         // cf2: m3 requires m2, m1
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -939,7 +1558,8 @@
 
         Configuration cf2 = resolveRequires(cf1, finder2, "m1", "m3");
 
-        assertTrue(cf2.parent().get() == cf1);
+        assertTrue(cf2.parents().size() == 1);
+        assertTrue(cf2.parents().get(0) == cf1);
 
         assertTrue(cf2.modules().size() == 2);
         assertTrue(cf2.findModule("m1").isPresent());
@@ -977,7 +1597,7 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testDirectDependencyNotFound() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1").requires("m2").build();
+            = ModuleDescriptor.module("m1").requires("m2").build();
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
         resolveRequires(finder, "m1");
     }
@@ -989,9 +1609,9 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testTransitiveDependencyNotFound() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1").requires("m2").build();
+            = ModuleDescriptor.module("m1").requires("m2").build();
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2").requires("m3").build();
+            = ModuleDescriptor.module("m2").requires("m3").build();
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
         resolveRequires(finder, "m1");
     }
@@ -1006,16 +1626,16 @@
         // service provider dependency (on m3) not found
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
                 .requires("m3")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -1032,11 +1652,11 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testSimpleCycle() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1").requires("m2").build();
+            = ModuleDescriptor.module("m1").requires("m2").build();
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2").requires("m3").build();
+            = ModuleDescriptor.module("m2").requires("m3").build();
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3").requires("m1").build();
+            = ModuleDescriptor.module("m3").requires("m1").build();
         ModuleFinder finder
             = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
         resolveRequires(finder, "m1");
@@ -1049,19 +1669,19 @@
     public void testCycleInProvider() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .uses("p.S")
                 .build();
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
                 .requires("m3")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -1080,19 +1700,19 @@
     public void testPackageSuppliedByTwoOthers() {
 
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
+            =  ModuleDescriptor.module("m1")
                 .requires("m2")
                 .requires("m3")
                 .build();
 
         ModuleDescriptor descriptor2
-            =  new ModuleDescriptor.Builder("m2")
+            =  ModuleDescriptor.module("m2")
                 .exports("p")
                 .build();
 
         ModuleDescriptor descriptor3
-            =  new ModuleDescriptor.Builder("m3")
-                .exports("p", "m1")
+            =  ModuleDescriptor.module("m3")
+                .exports("p", Set.of("m1"))
                 .build();
 
         ModuleFinder finder
@@ -1104,45 +1724,44 @@
 
 
     /**
-     * Test the scenario where a module has a concealed package p and reads
+     * Test the scenario where a module contains a package p and reads
      * a module that exports package p.
      */
     @Test(expectedExceptions = { ResolutionException.class })
     public void testPackageSuppliedBySelfAndOther() {
 
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
+            =  ModuleDescriptor.module("m1")
                 .requires("m2")
-                .conceals("p")
+                .contains("p")
                 .build();
 
         ModuleDescriptor descriptor2
-            =  new ModuleDescriptor.Builder("m2")
+            =  ModuleDescriptor.module("m2")
                 .exports("p")
                 .build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
 
-        //  m1 contains package p, module m2 exports package p to m1
+        // m1 contains package p, module m2 exports package p to m1
         resolveRequires(finder, "m1");
     }
 
 
     /**
-     * Test the scenario where a module has a concealed package p and reads
-     * a module that also has a concealed package p.
+     * Test the scenario where a module contains a package p and reads
+     * a module that also contains a package p.
      */
-    public void testPackagePrivateToSelfAndOther() {
-
+    public void testContainsPackageInSelfAndOther() {
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
+            =  ModuleDescriptor.module("m1")
                 .requires("m2")
-                .conceals("p")
+                .contains("p")
                 .build();
 
         ModuleDescriptor descriptor2
-            =  new ModuleDescriptor.Builder("m2")
-                .conceals("p")
+            =  ModuleDescriptor.module("m2")
+                .contains("p")
                 .build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
@@ -1169,7 +1788,7 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testExportSamePackageAsBootLayer() {
         ModuleDescriptor descriptor
-            =  new ModuleDescriptor.Builder("m1")
+            =  ModuleDescriptor.module("m1")
                 .requires("java.base")
                 .exports("java.lang")
                 .build();
@@ -1184,12 +1803,12 @@
 
 
     /**
-     * Test "uses p.S" where p is a concealed package in the same module.
+     * Test "uses p.S" where p is contained in the same module.
      */
-    public void testConcealedService1() {
+    public void testContainsService1() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
-                .conceals("p")
+            = ModuleDescriptor.module("m1")
+                .contains("p")
                 .uses("p.S")
                 .build();
 
@@ -1203,17 +1822,17 @@
 
 
     /**
-     * Test "uses p.S" where p is a concealed package in a different module.
+     * Test "uses p.S" where p is contained in a different module.
      */
     @Test(expectedExceptions = { ResolutionException.class })
-    public void testConcealedService2() {
+    public void testContainsService2() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
-                .conceals("p")
+            = ModuleDescriptor.module("m1")
+                .contains("p")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
                 .uses("p.S")
                 .build();
@@ -1226,13 +1845,13 @@
 
 
     /**
-     * Test "provides p.S" where p is a concealed package in the same module.
+     * Test "provides p.S" where p is contained in the same module.
      */
-    public void testConcealedService3() {
+    public void testContainsService3() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
-                .conceals("p")
-                .conceals("q")
+            = ModuleDescriptor.module("m1")
+                .contains("p")
+                .contains("q")
                 .provides("p.S", "q.S1")
                 .build();
 
@@ -1246,19 +1865,19 @@
 
 
     /**
-     * Test "provides p.S" where p is a concealed package in a different module.
+     * Test "provides p.S" where p is contained in a different module.
      */
     @Test(expectedExceptions = { ResolutionException.class })
-    public void testConcealedService4() {
+    public void testContainsService4() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
-                .conceals("p")
+            = ModuleDescriptor.module("m1")
+                .contains("p")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
-                .conceals("q")
+                .contains("q")
                 .provides("p.S", "q.S1")
                 .build();
 
@@ -1275,7 +1894,7 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testServiceTypePackageNotExported1() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .uses("p.S")
                 .build();
 
@@ -1292,8 +1911,8 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testServiceTypePackageNotExported2() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
-                .conceals("q")
+            = ModuleDescriptor.module("m1")
+                .contains("q")
                 .provides("p.S", "q.T")
                 .build();
 
@@ -1310,13 +1929,13 @@
     @Test(expectedExceptions = { ResolutionException.class })
     public void testProviderPackageNotLocal() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .exports("q")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m1")
                 .provides("p.S", "q.T")
                 .build();
@@ -1334,7 +1953,7 @@
     public void testEmptyConfiguration() {
         Configuration cf = Configuration.empty();
 
-        assertFalse(cf.parent().isPresent());
+        assertTrue(cf.parents().isEmpty());
 
         assertTrue(cf.modules().isEmpty());
         assertFalse(cf.findModule("java.base").isPresent());
@@ -1389,7 +2008,7 @@
     public void testPlatformMatch(String s1, String s2) {
 
         ModuleDescriptor.Builder builder
-            = new ModuleDescriptor.Builder("m1").requires("m2");
+            = ModuleDescriptor.module("m1").requires("m2");
 
         String[] s = s1.split("-");
         if (!s[0].equals("*"))
@@ -1401,7 +2020,7 @@
 
         ModuleDescriptor descriptor1 = builder.build();
 
-        builder = new ModuleDescriptor.Builder("m2");
+        builder = ModuleDescriptor.module("m2");
 
         s = s2.split("-");
         if (!s[0].equals("*"))
@@ -1433,6 +2052,21 @@
     }
 
 
+    // no parents
+
+    @Test(expectedExceptions = { IllegalArgumentException.class })
+    public void testResolveRequiresWithNoParents() {
+        ModuleFinder empty = ModuleFinder.of();
+        Configuration.resolveRequires(empty, List.of(), empty, Set.of());
+    }
+
+    @Test(expectedExceptions = { IllegalArgumentException.class })
+    public void testResolveRequiresAndUsesWithNoParents() {
+        ModuleFinder empty = ModuleFinder.of();
+        Configuration.resolveRequiresAndUses(empty, List.of(), empty, Set.of());
+    }
+
+
     // null handling
 
     // finder1, finder2, roots
@@ -1449,6 +2083,31 @@
     }
 
     @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresWithNull3() {
+        Configuration empty = Configuration.empty();
+        Configuration.resolveRequires(null, List.of(empty),  ModuleFinder.of(), Set.of());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresWithNull4() {
+        ModuleFinder empty = ModuleFinder.of();
+        Configuration.resolveRequires(empty, null, empty, Set.of());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresWithNull5() {
+        Configuration cf = Layer.boot().configuration();
+        Configuration.resolveRequires(ModuleFinder.of(), List.of(cf), null, Set.of());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresWithNull6() {
+        ModuleFinder empty = ModuleFinder.of();
+        Configuration cf = Layer.boot().configuration();
+        Configuration.resolveRequires(empty, List.of(cf), empty, null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
     public void testResolveRequiresAndUsesWithNull1() {
         resolveRequiresAndUses((ModuleFinder) null, ModuleFinder.of());
     }
@@ -1459,6 +2118,31 @@
     }
 
     @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresAndUsesWithNull3() {
+        Configuration empty = Configuration.empty();
+        Configuration.resolveRequiresAndUses(null, List.of(empty), ModuleFinder.of(), Set.of());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresAndUsesWithNull4() {
+        ModuleFinder empty = ModuleFinder.of();
+        Configuration.resolveRequiresAndUses(empty, null, empty, Set.of());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresAndUsesWithNull5() {
+        Configuration cf = Layer.boot().configuration();
+        Configuration.resolveRequiresAndUses(ModuleFinder.of(), List.of(cf), null, Set.of());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testResolveRequiresAndUsesWithNull6() {
+        ModuleFinder empty = ModuleFinder.of();
+        Configuration cf = Layer.boot().configuration();
+        Configuration.resolveRequiresAndUses(empty, List.of(cf), empty, null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
     public void testFindModuleWithNull() {
         Configuration.empty().findModule(null);
     }
diff --git a/jdk/test/java/lang/module/ModuleDescriptorTest.java b/jdk/test/java/lang/module/ModuleDescriptorTest.java
index 402d645..efaa498 100644
--- a/jdk/test/java/lang/module/ModuleDescriptorTest.java
+++ b/jdk/test/java/lang/module/ModuleDescriptorTest.java
@@ -23,28 +23,34 @@
 
 /**
  * @test
- * @modules java.base/jdk.internal.module
+ * @modules java.base/java.lang.module:open
+ *          java.base/jdk.internal.module
  * @run testng ModuleDescriptorTest
  * @summary Basic test for java.lang.module.ModuleDescriptor and its builder
  */
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.module.InvalidModuleDescriptorException;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Builder;
 import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleDescriptor.Provides;
 import java.lang.module.ModuleDescriptor.Requires.Modifier;
 import java.lang.module.ModuleDescriptor.Version;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Module;
 import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
 
@@ -72,7 +78,7 @@
     // requires
 
     private Requires requires(Set<Modifier> mods, String mn) {
-        return new Builder("m")
+        return ModuleDescriptor.module("m")
             .requires(mods, mn)
             .build()
             .requires()
@@ -80,19 +86,15 @@
             .next();
     }
 
-    public void testRequiresWithRequires() {
-        Requires r1 = requires(null, "foo");
-        ModuleDescriptor descriptor = new Builder("m").requires(r1).build();
-        Requires r2 = descriptor.requires().iterator().next();
-        assertEquals(r1, r2);
+    private Requires requires(String mn) {
+        return requires(Collections.emptySet(), mn);
     }
 
-    public void testRequiresWithNullModifiers() {
-        Requires r = requires(null, "foo");
-        assertEquals(r, r);
-        assertTrue(r.compareTo(r) == 0);
-        assertTrue(r.modifiers().isEmpty());
-        assertEquals(r.name(), "foo");
+    public void testRequiresWithRequires() {
+        Requires r1 = requires("foo");
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m").requires(r1).build();
+        Requires r2 = descriptor.requires().iterator().next();
+        assertEquals(r1, r2);
     }
 
     public void testRequiresWithNoModifiers() {
@@ -104,18 +106,18 @@
     }
 
     public void testRequiresWithOneModifier() {
-        Requires r = requires(EnumSet.of(PUBLIC), "foo");
+        Requires r = requires(EnumSet.of(TRANSITIVE), "foo");
         assertEquals(r, r);
         assertTrue(r.compareTo(r) == 0);
-        assertEquals(r.modifiers(), EnumSet.of(PUBLIC));
+        assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE));
         assertEquals(r.name(), "foo");
     }
 
     public void testRequiresWithTwoModifiers() {
-        Requires r = requires(EnumSet.of(PUBLIC, SYNTHETIC), "foo");
+        Requires r = requires(EnumSet.of(TRANSITIVE, SYNTHETIC), "foo");
         assertEquals(r, r);
         assertTrue(r.compareTo(r) == 0);
-        assertEquals(r.modifiers(), EnumSet.of(PUBLIC, SYNTHETIC));
+        assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, SYNTHETIC));
         assertEquals(r.name(), "foo");
     }
 
@@ -123,35 +125,35 @@
         Requires r = requires(EnumSet.allOf(Modifier.class), "foo");
         assertEquals(r, r);
         assertTrue(r.compareTo(r) == 0);
-        assertEquals(r.modifiers(), EnumSet.allOf(Modifier.class));
+        assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, STATIC, SYNTHETIC, MANDATED));
         assertEquals(r.name(), "foo");
     }
 
     @Test(expectedExceptions = IllegalStateException.class)
     public void testRequiresWithDuplicatesRequires() {
-        Requires r = requires(null, "foo");
-        new Builder("m").requires(r).requires(r);
+        Requires r = requires("foo");
+        ModuleDescriptor.module("m").requires(r).requires(r);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testRequiresSelfWithRequires() {
-        Requires r = requires(null, "foo");
-        new Builder("foo").requires(r);
+        Requires r = requires("foo");
+        ModuleDescriptor.module("foo").requires(r);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testRequiresSelfWithNoModifier() {
-        new Builder("m").requires("m");
+        ModuleDescriptor.module("m").requires("m");
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testRequiresSelfWithOneModifier() {
-        new Builder("m").requires(PUBLIC, "m");
+        ModuleDescriptor.module("m").requires(Set.of(TRANSITIVE), "m");
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testRequiresSelfWithAllModifiers() {
-        new Builder("m").requires(EnumSet.allOf(Modifier.class), "m");
+        ModuleDescriptor.module("m").requires(EnumSet.allOf(Modifier.class), "m");
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
@@ -162,7 +164,7 @@
 
     @Test(expectedExceptions = NullPointerException.class)
     public void testRequiresWithNullRequires() {
-        new Builder("m").requires((Requires) null);
+        ModuleDescriptor.module("m").requires((Requires) null);
     }
 
     public void testRequiresCompare() {
@@ -174,9 +176,9 @@
     }
 
     public void testRequiresCompareWithDifferentModifiers() {
-        Requires r1 = requires(EnumSet.of(PUBLIC), "foo");
+        Requires r1 = requires(EnumSet.of(TRANSITIVE), "foo");
         Requires r2 = requires(EnumSet.of(SYNTHETIC), "foo");
-        int n = Integer.compare(1 << PUBLIC.ordinal(), 1 << SYNTHETIC.ordinal());
+        int n = Integer.compare(1 << TRANSITIVE.ordinal(), 1 << SYNTHETIC.ordinal());
         assertTrue(r1.compareTo(r2) == n);
         assertTrue(r2.compareTo(r1) == -n);
     }
@@ -188,6 +190,26 @@
         assertTrue(r2.compareTo(r1) == 0);
     }
 
+    public void testRequiresEqualsAndHashCode() {
+        Requires r1 = requires("foo");
+        Requires r2 = requires("foo");
+        assertEquals(r1, r2);
+        assertTrue(r1.hashCode() == r2.hashCode());
+
+        r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
+        r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
+        assertEquals(r1, r2);
+        assertTrue(r1.hashCode() == r2.hashCode());
+
+        r1 = requires("foo");
+        r2 = requires("bar");
+        assertNotEquals(r1, r2);
+
+        r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
+        r2 = requires(Set.of(), "foo");
+        assertNotEquals(r1, r2);
+    }
+
     public void testRequiresToString() {
         Requires r = requires(EnumSet.noneOf(Modifier.class), "foo");
         assertTrue(r.toString().contains("foo"));
@@ -196,9 +218,22 @@
 
     // exports
 
+    private Exports exports(Set<Exports.Modifier> mods, String pn) {
+        return ModuleDescriptor.module("foo")
+            .exports(mods, pn)
+            .build()
+            .exports()
+            .iterator()
+            .next();
+    }
+
     private Exports exports(String pn) {
-        return new Builder("foo")
-            .exports(pn)
+        return exports(Set.of(), pn);
+    }
+
+    private Exports exports(Set<Exports.Modifier> mods, String pn, String target) {
+        return ModuleDescriptor.module("foo")
+            .exports(mods, pn, Set.of(target))
             .build()
             .exports()
             .iterator()
@@ -206,17 +241,13 @@
     }
 
     private Exports exports(String pn, String target) {
-        return new Builder("foo")
-            .exports(pn, target)
-            .build()
-            .exports()
-            .iterator()
-            .next();
+        return exports(Set.of(), pn, target);
     }
 
+
     public void testExportsExports() {
         Exports e1 = exports("p");
-        ModuleDescriptor descriptor = new Builder("m").exports(e1).build();
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m").exports(e1).build();
         Exports e2 = descriptor.exports().iterator().next();
         assertEquals(e1, e2);
     }
@@ -224,6 +255,7 @@
     public void testExportsToAll() {
         Exports e = exports("p");
         assertEquals(e, e);
+        assertTrue(e.modifiers().isEmpty());
         assertEquals(e.source(), "p");
         assertFalse(e.isQualified());
         assertTrue(e.targets().isEmpty());
@@ -232,6 +264,7 @@
     public void testExportsToTarget() {
         Exports e = exports("p", "bar");
         assertEquals(e, e);
+        assertTrue(e.modifiers().isEmpty());
         assertEquals(e.source(), "p");
         assertTrue(e.isQualified());
         assertTrue(e.targets().size() == 1);
@@ -243,13 +276,14 @@
         targets.add("bar");
         targets.add("gus");
         Exports e
-            = new Builder("foo")
+            = ModuleDescriptor.module("foo")
                 .exports("p", targets)
                 .build()
                 .exports()
                 .iterator()
                 .next();
         assertEquals(e, e);
+        assertTrue(e.modifiers().isEmpty());
         assertEquals(e.source(), "p");
         assertTrue(e.isQualified());
         assertTrue(e.targets().size() == 2);
@@ -257,56 +291,94 @@
         assertTrue(e.targets().contains("gus"));
     }
 
+    public void testExportsToAllWithModifier() {
+        Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
+        assertEquals(e, e);
+        assertTrue(e.modifiers().size() == 1);
+        assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
+        assertEquals(e.source(), "p");
+        assertFalse(e.isQualified());
+        assertTrue(e.targets().isEmpty());
+    }
+
+    public void testExportsToTargetWithModifier() {
+        Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p", "bar");
+        assertEquals(e, e);
+        assertTrue(e.modifiers().size() == 1);
+        assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
+        assertEquals(e.source(), "p");
+        assertTrue(e.isQualified());
+        assertTrue(e.targets().size() == 1);
+        assertTrue(e.targets().contains("bar"));
+    }
+
     @Test(expectedExceptions = IllegalStateException.class)
     public void testExportsWithDuplicate1() {
         Exports e = exports("p");
-        new Builder("foo").exports(e).exports(e);
+        ModuleDescriptor.module("foo").exports(e).exports(e);
     }
 
     @Test(expectedExceptions = IllegalStateException.class)
     public void testExportsWithDuplicate2() {
-        new Builder("foo").exports("p").exports("p");
+        ModuleDescriptor.module("foo").exports("p").exports("p");
     }
 
     @Test(expectedExceptions = IllegalStateException.class)
-    public void testExportsWithConcealedPackage() {
-        new Builder("foo").conceals("p").exports("p");
+    public void testExportsOnContainedPackage() {
+        ModuleDescriptor.module("foo").contains("p").exports("p");
     }
 
     @Test(expectedExceptions = IllegalStateException.class)
-    public void testExportsToTargetWithConcealedPackage() {
-        new Builder("foo").conceals("p").exports("p", "bar");
+    public void testExportsToTargetOnContainedPackage() {
+        ModuleDescriptor.module("foo").contains("p").exports("p", Set.of("bar"));
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class )
     public void testExportsWithEmptySet() {
-        new Builder("foo").exports("p", Collections.emptySet());
+        ModuleDescriptor.module("foo").exports("p", Collections.emptySet());
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
     public void testExportsWithBadName(String pn, String ignore) {
-        new Builder("foo").exports(pn);
+        ModuleDescriptor.module("foo").exports(pn);
     }
 
     @Test(expectedExceptions = NullPointerException.class )
     public void testExportsWithNullExports() {
-        new Builder("foo").exports((Exports)null);
-    }
-
-    @Test(expectedExceptions = IllegalArgumentException.class )
-    public void testExportsWithNullTarget() {
-        new Builder("foo").exports("p", (String) null);
+        ModuleDescriptor.module("foo").exports((Exports) null);
     }
 
     @Test(expectedExceptions = NullPointerException.class )
     public void testExportsWithNullTargets() {
-        new Builder("foo").exports("p", (Set<String>) null);
+        ModuleDescriptor.module("foo").exports("p", (Set<String>) null);
+    }
+
+    public void testExportsEqualsAndHashCode() {
+        Exports e1, e2;
+
+        e1 = exports("p");
+        e2 = exports("p");
+        assertEquals(e1, e2);
+        assertTrue(e1.hashCode() == e2.hashCode());
+
+        e1 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
+        e2 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
+        assertEquals(e1, e2);
+        assertTrue(e1.hashCode() == e2.hashCode());
+
+        e1 = exports("p");
+        e2 = exports("q");
+        assertNotEquals(e1, e2);
+
+        e1 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
+        e2 = exports(Set.of(), "p");
+        assertNotEquals(e1, e2);
     }
 
     public void testExportsToString() {
-        String s = new Builder("foo")
-            .exports("p1", "bar")
+        String s = ModuleDescriptor.module("foo")
+            .exports("p1", Set.of("bar"))
             .build()
             .exports()
             .iterator()
@@ -317,11 +389,188 @@
     }
 
 
+    // opens
+
+    private Opens opens(Set<Opens.Modifier> mods, String pn) {
+        return ModuleDescriptor.module("foo")
+                .opens(mods, pn)
+                .build()
+                .opens()
+                .iterator()
+                .next();
+    }
+
+    private Opens opens(String pn) {
+        return opens(Set.of(), pn);
+    }
+
+    private Opens opens(Set<Opens.Modifier> mods, String pn, String target) {
+        return ModuleDescriptor.module("foo")
+                .opens(mods, pn, Set.of(target))
+                .build()
+                .opens()
+                .iterator()
+                .next();
+    }
+
+    private Opens opens(String pn, String target) {
+        return opens(Set.of(), pn, target);
+    }
+
+    public void testOpensOpens() {
+        Opens o1 = opens("p");
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m").opens(o1).build();
+        Opens o2 = descriptor.opens().iterator().next();
+        assertEquals(o1, o2);
+    }
+
+    public void testOpensToAll() {
+        Opens o = opens("p");
+        assertEquals(o, o);
+        assertTrue(o.modifiers().isEmpty());
+        assertEquals(o.source(), "p");
+        assertFalse(o.isQualified());
+        assertTrue(o.targets().isEmpty());
+    }
+
+
+    public void testOpensToTarget() {
+        Opens o = opens("p", "bar");
+        assertEquals(o, o);
+        assertTrue(o.modifiers().isEmpty());
+        assertEquals(o.source(), "p");
+        assertTrue(o.isQualified());
+        assertTrue(o.targets().size() == 1);
+        assertTrue(o.targets().contains("bar"));
+    }
+
+    public void testOpensToTargets() {
+        Set<String> targets = new HashSet<>();
+        targets.add("bar");
+        targets.add("gus");
+        Opens o = ModuleDescriptor.module("foo")
+                .opens("p", targets)
+                .build()
+                .opens()
+                .iterator()
+                .next();
+        assertEquals(o, o);
+        assertTrue(o.modifiers().isEmpty());
+        assertEquals(o.source(), "p");
+        assertTrue(o.isQualified());
+        assertTrue(o.targets().size() == 2);
+        assertTrue(o.targets().contains("bar"));
+        assertTrue(o.targets().contains("gus"));
+    }
+
+    /*
+
+    public void testOpensToAllWithModifier() {
+        Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
+        assertEquals(e, e);
+        assertTrue(e.modifiers().size() == 1);
+        assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
+        assertEquals(e.source(), "p");
+        assertFalse(e.isQualified());
+        assertTrue(e.targets().isEmpty());
+    }
+
+    public void testOpensToTargetWithModifier() {
+        Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p", Set.of("bar"));
+        assertEquals(e, e);
+        assertTrue(e.modifiers().size() == 1);
+        assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
+        assertEquals(e.source(), "p");
+        assertTrue(e.isQualified());
+        assertTrue(e.targets().size() == 1);
+        assertTrue(e.targets().contains("bar"));
+    }
+
+
+    */
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testOpensWithDuplicate1() {
+        Opens o = opens("p");
+        ModuleDescriptor.module("foo").opens(o).opens(o);
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testOpensWithDuplicate2() {
+        ModuleDescriptor.module("foo").opens("p").opens("p");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testOpensOnContainedPackage() {
+        ModuleDescriptor.module("foo").contains("p").opens("p");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testOpensToTargetOnContainedPackage() {
+        ModuleDescriptor.module("foo").contains("p").opens("p", Set.of("bar"));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class )
+    public void testOpensWithEmptySet() {
+        ModuleDescriptor.module("foo").opens("p", Collections.emptySet());
+    }
+
+    @Test(dataProvider = "invalidjavaidentifiers",
+            expectedExceptions = IllegalArgumentException.class )
+    public void testOpensWithBadName(String pn, String ignore) {
+        ModuleDescriptor.module("foo").opens(pn);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class )
+    public void testOpensWithNullExports() {
+        ModuleDescriptor.module("foo").opens((Opens) null);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class )
+    public void testOpensWithNullTargets() {
+        ModuleDescriptor.module("foo").opens("p", (Set<String>) null);
+    }
+
+    public void testOpensEqualsAndHashCode() {
+        Opens o1, o2;
+
+        o1 = opens("p");
+        o2 = opens("p");
+        assertEquals(o1, o2);
+        assertTrue(o1.hashCode() == o1.hashCode());
+
+        o1 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
+        o2 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
+        assertEquals(o1, o2);
+        assertTrue(o1.hashCode() == o2.hashCode());
+
+        o1 = opens("p");
+        o2 = opens("q");
+        assertNotEquals(o1, o2);
+
+        o1 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
+        o2 = opens(Set.of(), "p");
+        assertNotEquals(o1, o2);
+    }
+
+    public void testOpensToString() {
+        String s = ModuleDescriptor.module("foo")
+                .opens("p1", Set.of("bar"))
+                .build()
+                .opens()
+                .iterator()
+                .next()
+                .toString();
+        assertTrue(s.contains("p1"));
+        assertTrue(s.contains("bar"));
+    }
+
+
     // uses
 
     public void testUses() {
         Set<String> uses
-            = new Builder("foo")
+            = ModuleDescriptor.module("foo")
                 .uses("p.S")
                 .uses("q.S")
                 .build()
@@ -333,126 +582,148 @@
 
     @Test(expectedExceptions = IllegalStateException.class)
     public void testUsesWithDuplicate() {
-        new Builder("foo").uses("p.S").uses("p.S");
+        ModuleDescriptor.module("foo").uses("p.S").uses("p.S");
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
     public void testUsesWithBadName(String service, String ignore) {
-        new Builder("foo").uses(service);
+        ModuleDescriptor.module("foo").uses(service);
     }
 
 
     // provides
 
     private Provides provides(String st, String pc) {
-        return new Builder("foo")
+        return ModuleDescriptor.module("foo")
             .provides(st, pc)
             .build()
             .provides()
-            .values()
             .iterator()
             .next();
     }
 
     public void testProvidesWithProvides() {
         Provides p1 = provides("p.S", "q.S1");
-        ModuleDescriptor descriptor = new Builder("m").provides(p1).build();
-        Provides p2 = descriptor.provides().get("p.S");
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m")
+                .provides(p1)
+                .build();
+        Provides p2 = descriptor.provides().iterator().next();
         assertEquals(p1, p2);
     }
 
-    public void testProvides() {
-        Set<String> pns = new HashSet<>();
-        pns.add("q.P1");
-        pns.add("q.P2");
 
-        Map<String, Provides> map
-            = new Builder("foo")
-                .provides("p.S", pns)
+    public void testProvides() {
+        Set<Provides> set = ModuleDescriptor.module("foo")
+                .provides("p.S", List.of("q.P1", "q.P2"))
                 .build()
                 .provides();
-        assertTrue(map.size() == 1);
+        assertTrue(set.size() == 1);
 
-        Provides p = map.values().iterator().next();
+        Provides p = set.iterator().next();
         assertEquals(p, p);
+        assertEquals(p.service(), "p.S");
         assertTrue(p.providers().size() == 2);
-        assertTrue(p.providers().contains("q.P1"));
-        assertTrue(p.providers().contains("q.P2"));
+        assertEquals(p.providers().get(0), "q.P1");
+        assertEquals(p.providers().get(1), "q.P2");
     }
 
     @Test(expectedExceptions = IllegalStateException.class )
     public void testProvidesWithDuplicateProvides() {
         Provides p = provides("p.S", "q.S2");
-        new Builder("m").provides("p.S", "q.S1").provides(p);
+        ModuleDescriptor.module("m").provides("p.S", "q.S1").provides(p);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class )
     public void testProvidesWithEmptySet() {
-        new Builder("foo").provides("p.Service", Collections.emptySet());
+        ModuleDescriptor.module("foo").provides("p.Service", Collections.emptyList());
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
     public void testProvidesWithBadService(String service, String ignore) {
-        new Builder("foo").provides(service, "p.Provider");
+        ModuleDescriptor.module("foo").provides(service, "p.Provider");
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
     public void testProvidesWithBadProvider(String provider, String ignore) {
-        new Builder("foo").provides("p.Service", provider);
+        ModuleDescriptor.module("foo").provides("p.Service", provider);
     }
 
     @Test(expectedExceptions = NullPointerException.class )
     public void testProvidesWithNullProvides() {
-        new Builder("foo").provides((Provides)null);
+        ModuleDescriptor.module("foo").provides((Provides) null);
     }
 
     @Test(expectedExceptions = NullPointerException.class )
     public void testProvidesWithNullProviders() {
-        new Builder("foo").provides("p.S", (Set<String>) null);
+        ModuleDescriptor.module("foo").provides("p.S", (List<String>) null);
     }
 
+    public void testProvidesEqualsAndHashCode() {
+        Provides p1, p2;
 
-    // conceals
+        p1 = provides("p.S", "q.S1");
+        p2 = provides("p.S", "q.S1");
+        assertEquals(p1, p2);
+        assertTrue(p1.hashCode() == p2.hashCode());
 
-    public void testConceals() {
-        Set<String> conceals
-            = new Builder("foo").conceals("p").conceals("q").build().conceals();
-        assertTrue(conceals.size() == 2);
-        assertTrue(conceals.contains("p"));
-        assertTrue(conceals.contains("q"));
+        p1 = provides("p.S", "q.S1");
+        p2 = provides("p.S", "q.S2");
+        assertNotEquals(p1, p2);
+
+        p1 = provides("p.S", "q.S1");
+        p2 = provides("p.S2", "q.S1");
+        assertNotEquals(p1, p2);
     }
 
-    public void testConcealsWithEmptySet() {
-        Set<String> conceals
-            = new Builder("foo").conceals(Collections.emptySet()).build().conceals();
-        assertTrue(conceals.size() == 0);
+    // contains
+
+    public void testContains() {
+        Set<String> packages = ModuleDescriptor.module("foo")
+                .contains("p")
+                .contains("q")
+                .build()
+                .packages();
+        assertTrue(packages.size() == 2);
+        assertTrue(packages.contains("p"));
+        assertTrue(packages.contains("q"));
+    }
+
+    public void testContainsWithEmptySet() {
+        Set<String> packages = ModuleDescriptor.module("foo")
+                .contains(Collections.emptySet())
+                .build()
+                .packages();
+        assertTrue(packages.size() == 0);
     }
 
     @Test(expectedExceptions = IllegalStateException.class)
-    public void testConcealsWithDuplicate() {
-        new Builder("foo").conceals("p").conceals("p");
+    public void testContainsWithDuplicate() {
+        ModuleDescriptor.module("foo").contains("p").contains("p");
     }
 
     @Test(expectedExceptions = IllegalStateException.class)
-    public void testConcealsWithExportedPackage() {
-        new Builder("foo").exports("p").conceals("p");
+    public void testContainsWithExportedPackage() {
+        ModuleDescriptor.module("foo").exports("p").contains("p");
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
-    public void testConcealsWithBadName(String pn, String ignore) {
-        new Builder("foo").conceals(pn);
+    public void testContainsWithBadName(String pn, String ignore) {
+        ModuleDescriptor.module("foo").contains(pn);
     }
 
 
     // packages
 
     public void testPackages() {
-        Set<String> packages
-            = new Builder("foo").exports("p").conceals("q").build().packages();
+        Set<String> packages = ModuleDescriptor.module("foo")
+                .exports("p")
+                .contains("q")
+                .build()
+                .packages();
         assertTrue(packages.size() == 2);
         assertTrue(packages.contains("p"));
         assertTrue(packages.contains("q"));
@@ -462,14 +733,14 @@
     // name
 
     public void testModuleName() {
-        String mn = new Builder("foo").build().name();
+        String mn = ModuleDescriptor.module("foo").build().name();
         assertEquals(mn, "foo");
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
     public void testBadModuleName(String mn, String ignore) {
-        new Builder(mn);
+        ModuleDescriptor.module(mn);
     }
 
 
@@ -477,67 +748,107 @@
 
     public void testVersion1() {
         Version v1 = Version.parse("1.0");
-        Version v2 = new Builder("foo").version(v1).build().version().get();
+        Version v2 = ModuleDescriptor.module("foo")
+                .version(v1)
+                .build()
+                .version()
+                .get();
         assertEquals(v1, v2);
     }
 
     public void testVersion2() {
         String vs = "1.0";
-        Version v1 = new Builder("foo").version(vs).build().version().get();
+        Version v1 = ModuleDescriptor.module("foo")
+                .version(vs)
+                .build()
+                .version()
+                .get();
         Version v2 = Version.parse(vs);
         assertEquals(v1, v2);
     }
 
     @Test(expectedExceptions = NullPointerException.class )
     public void testNullVersion1() {
-        new Builder("foo").version((Version)null);
+        ModuleDescriptor.module("foo").version((Version) null);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class )
     public void testNullVersion2() {
-        new Builder("foo").version((String)null);
+        ModuleDescriptor.module("foo").version((String) null);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class )
     public void testEmptyVersion() {
-        new Builder("foo").version("");
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testDuplicateVersion1() {
-        Version v = Version.parse("2.0");
-        new Builder("foo").version("1.0").version(v);
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testDuplicateVersion2() {
-        new Builder("foo").version("1.0").version("2.0");
+        ModuleDescriptor.module("foo").version("");
     }
 
 
     // toNameAndVersion
 
     public void testToNameAndVersion() {
-        ModuleDescriptor md1 = new Builder("foo").build();
+        ModuleDescriptor md1 = ModuleDescriptor.module("foo").build();
         assertEquals(md1.toNameAndVersion(), "foo");
 
-        ModuleDescriptor md2 = new Builder("foo").version("1.0").build();
+        ModuleDescriptor md2 = ModuleDescriptor.module("foo").version("1.0").build();
         assertEquals(md2.toNameAndVersion(), "foo@1.0");
     }
 
 
-    // isAutomatic
+    // open modules
+
+    public void testOpenModules() {
+        ModuleDescriptor descriptor = ModuleDescriptor.openModule("m")
+                .requires("java.base")
+                .contains("p")
+                .build();
+        assertTrue(descriptor.isOpen());
+        assertTrue(descriptor.packages().size() == 1);
+        assertTrue(descriptor.packages().contains("p"));
+        assertTrue(descriptor.exports().isEmpty());
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testOpensOnWeakModule1() {
+        ModuleDescriptor.openModule("foo").opens("p");
+    }
+
+    @Test(expectedExceptions = IllegalStateException.class)
+    public void testOpensOnWeakModule2() {
+        ModuleDescriptor.openModule("foo").opens("p", Set.of("bar"));
+    }
+
+    public void testIsOpen() {
+        assertFalse(ModuleDescriptor.module("m").build().isOpen());
+        assertFalse(ModuleDescriptor.automaticModule("m").build().isOpen());
+        assertTrue(ModuleDescriptor.openModule("m").build().isOpen());
+    }
+
+
+    // automatic modules
+
     public void testIsAutomatic() {
-        ModuleDescriptor descriptor = new Builder("foo").build();
-        assertFalse(descriptor.isAutomatic());
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module("foo").build();
+        assertFalse(descriptor1.isAutomatic());
+
+        ModuleDescriptor descriptor2 = ModuleDescriptor.openModule("foo").build();
+        assertFalse(descriptor2.isAutomatic());
+
+        ModuleDescriptor descriptor3 = ModuleDescriptor.automaticModule("foo").build();
+        assertTrue(descriptor3.isAutomatic());
     }
 
     // isSynthetic
     public void testIsSynthetic() {
         assertFalse(Object.class.getModule().getDescriptor().isSynthetic());
 
-        ModuleDescriptor descriptor = new Builder("foo").build();
-        assertFalse(descriptor.isSynthetic());
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module("foo").build();
+        assertFalse(descriptor1.isSynthetic());
+
+        ModuleDescriptor descriptor2 = ModuleDescriptor.openModule("foo").build();
+        assertFalse(descriptor2.isSynthetic());
+
+        ModuleDescriptor descriptor3 = ModuleDescriptor.automaticModule("foo").build();
+        assertFalse(descriptor3.isSynthetic());
     }
 
 
@@ -545,92 +856,71 @@
 
     public void testMainClass() {
         String mainClass
-            = new Builder("foo").mainClass("p.Main").build().mainClass().get();
+            = ModuleDescriptor.module("foo").mainClass("p.Main").build().mainClass().get();
         assertEquals(mainClass, "p.Main");
     }
 
     @Test(dataProvider = "invalidjavaidentifiers",
           expectedExceptions = IllegalArgumentException.class )
     public void testMainClassWithBadName(String mainClass, String ignore) {
-        Builder builder = new Builder("foo");
+        Builder builder = ModuleDescriptor.module("foo");
         builder.mainClass(mainClass);
     }
 
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testDuplicateMainClass() {
-        new Builder("foo").mainClass("p.Main").mainClass("p.Main");
-    }
-
 
     // osName
 
     public void testOsName() {
-        String osName = new Builder("foo").osName("Linux").build().osName().get();
+        String osName = ModuleDescriptor.module("foo").osName("Linux").build().osName().get();
         assertEquals(osName, "Linux");
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testNullOsName() {
-        new Builder("foo").osName(null);
+        ModuleDescriptor.module("foo").osName(null);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testEmptyOsName() {
-        new Builder("foo").osName("");
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testDuplicateOsName() {
-        new Builder("foo").osName("Linux").osName("Linux");
+        ModuleDescriptor.module("foo").osName("");
     }
 
 
     // osArch
 
     public void testOsArch() {
-        String osArch = new Builder("foo").osName("arm").build().osName().get();
+        String osArch = ModuleDescriptor.module("foo").osName("arm").build().osName().get();
         assertEquals(osArch, "arm");
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testNullOsArch() {
-        new Builder("foo").osArch(null);
+        ModuleDescriptor.module("foo").osArch(null);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testEmptyOsArch() {
-        new Builder("foo").osArch("");
-    }
-
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testDuplicateOsArch() {
-        new Builder("foo").osArch("arm").osArch("arm");
+        ModuleDescriptor.module("foo").osArch("");
     }
 
 
     // osVersion
 
     public void testOsVersion() {
-        String osVersion = new Builder("foo").osName("11.2").build().osName().get();
+        String osVersion = ModuleDescriptor.module("foo").osName("11.2").build().osName().get();
         assertEquals(osVersion, "11.2");
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testNullOsVersion() {
-        new Builder("foo").osVersion(null);
+        ModuleDescriptor.module("foo").osVersion(null);
     }
 
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testEmptyOsVersion() {
-        new Builder("foo").osVersion("");
+        ModuleDescriptor.module("foo").osVersion("");
     }
 
-    @Test(expectedExceptions = IllegalStateException.class)
-    public void testDuplicateOsVersion() {
-        new Builder("foo").osVersion("11.2").osVersion("11.2");
-    }
-
-
     // reads
 
     private static InputStream EMPTY_INPUT_STREAM = new InputStream() {
@@ -647,7 +937,8 @@
         }
     };
 
-    public void testRead() throws Exception {
+    // basic test reading module-info.class
+    public void testRead1() throws Exception {
         Module base = Object.class.getModule();
 
         try (InputStream in = base.getResourceAsStream("module-info.class")) {
@@ -664,9 +955,80 @@
         }
     }
 
-    public void testReadsWithPackageFinder() {
-        // TBD: Need way to write a module-info.class without a
-        // ConcealedPackages attribute
+    /**
+     * Test reading a module-info.class that has a module name, requires,
+     * and qualified exports with module names that are not supported in the
+     * Java Language.
+     */
+    public void testRead2() throws Exception {
+        // use non-public constructor to create a Builder that is not strict
+        Constructor<?> ctor = Builder.class.getDeclaredConstructor(String.class, boolean.class);
+        ctor.setAccessible(true);
+
+        Builder builder = (ModuleDescriptor.Builder) ctor.newInstance("m?1", false);
+        ModuleDescriptor descriptor = builder
+                .requires("java.base")
+                .requires("-m1")
+                .exports("p", Set.of("m2-"))
+                .build();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ModuleInfoWriter.write(descriptor, baos);
+        ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
+
+        descriptor = ModuleDescriptor.read(bb);
+        assertEquals(descriptor.name(), "m?1");
+
+        Set<String> requires = descriptor.requires()
+                .stream()
+                .map(Requires::name)
+                .collect(Collectors.toSet());
+        assertTrue(requires.size() == 2);
+        assertTrue(requires.contains("java.base"));
+        assertTrue(requires.contains("-m1"));
+
+        assertTrue(descriptor.exports().size() == 1);
+        Exports e = descriptor.exports().iterator().next();
+        assertTrue(e.targets().size() == 1);
+        assertTrue(e.targets().contains("m2-"));
+    }
+
+    /**
+     * Test ModuleDescriptor with a packager finder
+     */
+    public void testReadsWithPackageFinder() throws Exception {
+        ModuleDescriptor descriptor = ModuleDescriptor.module("foo")
+                .requires("java.base")
+                .build();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ModuleInfoWriter.write(descriptor, baos);
+        ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
+
+        descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
+
+        assertTrue(descriptor.packages().size() == 2);
+        assertTrue(descriptor.packages().contains("p"));
+        assertTrue(descriptor.packages().contains("q"));
+    }
+
+    /**
+     * Test ModuleDescriptor with a packager finder that doesn't return the
+     * complete set of packages.
+     */
+    @Test(expectedExceptions = InvalidModuleDescriptorException.class)
+    public void testReadsWithBadPackageFinder() throws Exception {
+        ModuleDescriptor descriptor = ModuleDescriptor.module("foo")
+                .requires("java.base")
+                .exports("p")
+                .build();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ModuleInfoWriter.write(descriptor, baos);
+        ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
+
+        // package finder returns a set that doesn't include p
+        ModuleDescriptor.read(bb, () -> Set.of("q"));
     }
 
     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
@@ -689,7 +1051,7 @@
     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
     public void testReadOfJavaBaseWithRequires() {
         ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder("java.base")
+            = ModuleDescriptor.module("java.base")
                 .requires("other")
                 .build();
         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
@@ -699,7 +1061,7 @@
     // The requires table must have an entry for java.base
     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
     public void testReadWithEmptyRequires() {
-        ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1").build();
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m1").build();
         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
         ModuleDescriptor.read(bb);
     }
@@ -708,14 +1070,13 @@
     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
     public void testReadWithNoRequiresBase() {
         ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("m2")
                 .build();
         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
         ModuleDescriptor.read(bb);
     }
 
-
     public void testReadWithNull() throws Exception {
         Module base = Object.class.getModule();
 
@@ -751,22 +1112,22 @@
     // equals/hashCode/compareTo/toString
 
     public void testEqualsAndHashCode() {
-        ModuleDescriptor md1 = new Builder("foo").build();
-        ModuleDescriptor md2 = new Builder("foo").build();
+        ModuleDescriptor md1 = ModuleDescriptor.module("foo").build();
+        ModuleDescriptor md2 = ModuleDescriptor.module("foo").build();
         assertEquals(md1, md1);
         assertEquals(md1.hashCode(), md2.hashCode());
     }
 
     public void testCompare() {
-        ModuleDescriptor md1 = new Builder("foo").build();
-        ModuleDescriptor md2 = new Builder("bar").build();
+        ModuleDescriptor md1 = ModuleDescriptor.module("foo").build();
+        ModuleDescriptor md2 = ModuleDescriptor.module("bar").build();
         int n = "foo".compareTo("bar");
         assertTrue(md1.compareTo(md2) == n);
         assertTrue(md2.compareTo(md1) == -n);
     }
 
     public void testToString() {
-        String s = new Builder("m1").requires("m2").exports("p1").build().toString();
+        String s = ModuleDescriptor.module("m1").requires("m2").exports("p1").build().toString();
         assertTrue(s.contains("m1"));
         assertTrue(s.contains("m2"));
         assertTrue(s.contains("p1"));
diff --git a/jdk/test/java/lang/module/ModuleFinderTest.java b/jdk/test/java/lang/module/ModuleFinderTest.java
index 9a79a57..278b4b9 100644
--- a/jdk/test/java/lang/module/ModuleFinderTest.java
+++ b/jdk/test/java/lang/module/ModuleFinderTest.java
@@ -335,7 +335,7 @@
 
         ModuleFinder finder = ModuleFinder.of(jar);
         Optional<ModuleReference> mref = finder.find("m");
-        assertTrue(mref.isPresent(), "m not found");
+        assertTrue(mref.isPresent(), "m1 not found");
 
         ModuleDescriptor descriptor = mref.get().descriptor();
 
@@ -748,7 +748,7 @@
             vs = mid.substring(i+1);
         }
         ModuleDescriptor.Builder builder
-            = new ModuleDescriptor.Builder(mn).requires("java.base");
+            = ModuleDescriptor.module(mn).requires("java.base");
         if (vs != null)
             builder.version(vs);
         return builder.build();
diff --git a/jdk/test/java/lang/module/ModuleReferenceTest.java b/jdk/test/java/lang/module/ModuleReferenceTest.java
index fca7cc77..6b480bb 100644
--- a/jdk/test/java/lang/module/ModuleReferenceTest.java
+++ b/jdk/test/java/lang/module/ModuleReferenceTest.java
@@ -45,10 +45,10 @@
 
     public void testBasic() throws Exception {
         ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder("m")
+            = ModuleDescriptor.module("m")
                 .exports("p")
                 .exports("q")
-                .conceals("p.internal")
+                .contains("p.internal")
                 .build();
 
         URI uri = URI.create("module:/m");
@@ -76,7 +76,7 @@
 
     public void testNullLocation() {
         ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder("m")
+            = ModuleDescriptor.module("m")
                 .exports("p")
                 .build();
         Supplier<ModuleReader> supplier = makeSupplier();
@@ -86,7 +86,7 @@
 
     @Test(expectedExceptions = { NullPointerException.class })
     public void testNullSupplier() throws Exception {
-        ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m").build();
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m").build();
         URI location = URI.create("module:/m");
         new ModuleReference(descriptor, location, null);
     }
@@ -94,11 +94,11 @@
 
     public void testEqualsAndHashCode() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .build();
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .exports("p")
                 .build();
 
@@ -121,7 +121,7 @@
 
 
     public void testToString() {
-        ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1").build();
+        ModuleDescriptor descriptor = ModuleDescriptor.module("m1").build();
         URI uri = URI.create("module:/m1");
         Supplier<ModuleReader> supplier = makeSupplier();
         ModuleReference mref = new ModuleReference(descriptor, uri, supplier);
diff --git a/jdk/test/java/lang/module/MultiReleaseJarTest.java b/jdk/test/java/lang/module/MultiReleaseJarTest.java
index ad98265..7daddb1 100644
--- a/jdk/test/java/lang/module/MultiReleaseJarTest.java
+++ b/jdk/test/java/lang/module/MultiReleaseJarTest.java
@@ -80,7 +80,7 @@
     public void testBasic() throws Exception {
         String name = "m1";
 
-        ModuleDescriptor descriptor = new ModuleDescriptor.Builder(name)
+        ModuleDescriptor descriptor = ModuleDescriptor.module(name)
                 .requires("java.base")
                 .build();
 
@@ -117,12 +117,12 @@
     public void testModuleInfoInVersionedSection() throws Exception {
         String name = "m1";
 
-        ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder(name)
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module(name)
                 .requires("java.base")
                 .build();
 
         // module descriptor for versioned section
-        ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder(name)
+        ModuleDescriptor descriptor2 = ModuleDescriptor.module(name)
                 .requires("java.base")
                 .requires("jdk.unsupported")
                 .build();
@@ -188,12 +188,12 @@
     public void testModuleReader() throws Exception {
         String name = "m1";
 
-        ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder(name)
+        ModuleDescriptor descriptor1 = ModuleDescriptor.module(name)
                 .requires("java.base")
                 .build();
 
         // module descriptor for versioned section
-        ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder(name)
+        ModuleDescriptor descriptor2 = ModuleDescriptor.module(name)
                 .requires("java.base")
                 .requires("jdk.unsupported")
                 .build();
diff --git a/jdk/test/java/lang/ref/FinalizerHistogramTest.java b/jdk/test/java/lang/ref/FinalizerHistogramTest.java
index a201331..66cf76e 100644
--- a/jdk/test/java/lang/ref/FinalizerHistogramTest.java
+++ b/jdk/test/java/lang/ref/FinalizerHistogramTest.java
@@ -31,6 +31,7 @@
 /*
  * @test
  * @summary Unit test for FinalizerHistogram
+ * @modules java.base/java.lang.ref:open
  * @run main FinalizerHistogramTest
  */
 
diff --git a/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java b/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
index 8d91966..da5d264 100644
--- a/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
+++ b/jdk/test/java/lang/reflect/AccessibleObject/ModuleSetAccessibleTest.java
@@ -24,7 +24,8 @@
 /**
  * @test
  * @build ModuleSetAccessibleTest
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/java.lang:open
+ *          java.base/jdk.internal.misc:+open
  * @run testng ModuleSetAccessibleTest
  * @summary Test java.lang.reflect.AccessibleObject with modules
  */
@@ -142,81 +143,6 @@
 
 
     /**
-     * Test that only public members of java.lang.reflect.Module can be make
-     * accessible.
-     */
-    public void testJavaLangReflectModule() throws Exception {
-
-        // non-public constructor
-        Constructor<?> ctor
-            = Module.class.getDeclaredConstructor(ClassLoader.class,
-                                                  ModuleDescriptor.class);
-        AccessibleObject[] ctors = { ctor };
-
-        try {
-            ctor.setAccessible(true);
-            assertTrue(false);
-        } catch (InaccessibleObjectException expected) { }
-
-        try {
-            AccessibleObject.setAccessible(ctors, true);
-            assertTrue(false);
-        } catch (InaccessibleObjectException expected) { }
-
-        // should succeed
-        ctor.setAccessible(false);
-        AccessibleObject.setAccessible(ctors, false);
-
-
-        // public method
-        Method method = Module.class.getMethod("addReads", Module.class);
-        AccessibleObject[] methods = { method };
-        method.setAccessible(true);
-        AccessibleObject.setAccessible(methods, true);
-        method.setAccessible(false);
-        AccessibleObject.setAccessible(methods, false);
-
-        // non-public method
-        method = Module.class.getDeclaredMethod("implAddReadsNoSync", Module.class);
-        methods[0] = method;
-
-        try {
-            method.setAccessible(true);
-            assertTrue(false);
-        } catch (InaccessibleObjectException expected) { }
-
-        try {
-            AccessibleObject.setAccessible(methods, true);
-            assertTrue(false);
-        } catch (InaccessibleObjectException expected) { }
-
-        // should succeed
-        method.setAccessible(false);
-        AccessibleObject.setAccessible(methods, false);
-
-
-        // non-public field
-        Field field = Module.class.getDeclaredField("name");
-        AccessibleObject[] fields = { field };
-
-        try {
-            field.setAccessible(true);
-            assertTrue(false);
-        } catch (InaccessibleObjectException expected) { }
-
-        try {
-            AccessibleObject.setAccessible(fields, true);
-            assertTrue(false);
-        } catch (InaccessibleObjectException expected) { }
-
-        // should succeed
-        field.setAccessible(false);
-        AccessibleObject.setAccessible(fields, false);
-
-    }
-
-
-    /**
      * Test that the Class constructor cannot be make accessible.
      */
     public void testJavaLangClass() throws Exception {
diff --git a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java
index 1241f23..8f14171 100644
--- a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java
+++ b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java
@@ -32,12 +32,14 @@
 
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Requires;
 import java.lang.module.ModuleFinder;
 import java.lang.reflect.Layer;
 import java.lang.reflect.LayerInstantiationException;
 import java.lang.reflect.Module;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -53,7 +55,7 @@
     public void testEmpty() {
         Layer emptyLayer = Layer.empty();
 
-        assertFalse(emptyLayer.parent().isPresent());
+        assertTrue(emptyLayer.parents().isEmpty());
 
         assertTrue(emptyLayer.configuration() == Configuration.empty());
 
@@ -97,8 +99,9 @@
         // findLoader
         assertTrue(bootLayer.findLoader("java.base") == null);
 
-        // parent
-        assertTrue(bootLayer.parent().get() == Layer.empty());
+        // parents
+        assertTrue(bootLayer.parents().size() == 1);
+        assertTrue(bootLayer.parents().get(0) == Layer.empty());
     }
 
 
@@ -107,18 +110,18 @@
      */
     public void testLayerOnEmpty() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("m2")
                 .exports("p1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("m3")
                 .build();
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .build();
 
         ModuleFinder finder
@@ -178,8 +181,9 @@
             assertTrue(false);
         } catch (IllegalArgumentException ignore) { }
 
-        // parent
-        assertTrue(layer.parent().get() == Layer.empty());
+        // parents
+        assertTrue(layer.parents().size() == 1);
+        assertTrue(layer.parents().get(0) == Layer.empty());
     }
 
 
@@ -188,14 +192,14 @@
      */
     public void testLayerOnBoot() {
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("m2")
                 .requires("java.base")
                 .exports("p1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
+            = ModuleDescriptor.module("m2")
                 .requires("java.base")
                 .build();
 
@@ -241,8 +245,9 @@
         assertTrue(layer.findLoader("m2") == loader);
         assertTrue(layer.findLoader("java.base") == null);
 
-        // parent
-        assertTrue(layer.parent().get() == Layer.boot());
+        // parents
+        assertTrue(layer.parents().size() == 1);
+        assertTrue(layer.parents().get(0) == Layer.boot());
     }
 
 
@@ -250,16 +255,16 @@
      * Exercise Layer defineModules with a configuration of two modules that
      * have the same module-private package.
      */
-    public void testSameConcealedPackage() {
+    public void testPackageContainedInSelfAndOther() {
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
+            =  ModuleDescriptor.module("m1")
                 .requires("m2")
-                .conceals("p")
+                .contains("p")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .conceals("p")
+            = ModuleDescriptor.module("m2")
+                .contains("p")
                 .build();
 
         ModuleFinder finder
@@ -288,22 +293,22 @@
 
         // m1 reads m2, m2 exports p to m1
         ModuleDescriptor descriptor1
-            =  new ModuleDescriptor.Builder("m1")
+            =  ModuleDescriptor.module("m1")
                 .requires("m2")
                 .build();
         ModuleDescriptor descriptor2
-            =  new ModuleDescriptor.Builder("m2")
-                .exports("p", "m1")
+            =  ModuleDescriptor.module("m2")
+                .exports("p", Set.of("m1"))
                 .build();
 
         // m3 reads m4, m4 exports p to m3
         ModuleDescriptor descriptor3
-            =  new ModuleDescriptor.Builder("m3")
+            =  ModuleDescriptor.module("m3")
                 .requires("m4")
                 .build();
         ModuleDescriptor descriptor4
-            =  new ModuleDescriptor.Builder("m4")
-                .exports("p", "m3")
+            =  ModuleDescriptor.module("m4")
+                .exports("p", Set.of("m3"))
                 .build();
 
         ModuleFinder finder
@@ -325,7 +330,7 @@
         map.put("m1", loader1);
         map.put("m2", loader1);
         map.put("m3", loader2);
-        map.put("m3", loader2);
+        map.put("m4", loader2);
         Layer.empty().defineModules(cf, map::get);
 
         // same loader
@@ -338,20 +343,20 @@
 
 
     /**
-     * Exercise Layer defineModules with a configuration that contains a module
-     * that has a concealed package that is the same name as a non-exported
-     * package in a parent layer.
+     * Exercise Layer defineModules with a configuration with a module that
+     * contains a package that is the same name as a non-exported package in
+     * a parent layer.
      */
-    public void testConcealSamePackageAsBootLayer() {
+    public void testContainsSamePackageAsBootLayer() {
 
         // check assumption that java.base contains sun.launcher
         ModuleDescriptor base = Object.class.getModule().getDescriptor();
-        assertTrue(base.conceals().contains("sun.launcher"));
+        assertTrue(base.packages().contains("sun.launcher"));
 
         ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                .requires("java.base")
-               .conceals("sun.launcher")
+               .contains("sun.launcher")
                .build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor);
@@ -370,20 +375,20 @@
      * Test layers with implied readability.
      *
      * The test consists of three configurations:
-     * - Configuration/layer1: m1, m2 requires public m1
+     * - Configuration/layer1: m1, m2 requires transitive m1
      * - Configuration/layer2: m3 requires m1
      */
     public void testImpliedReadabilityWithLayers1() {
 
-        // cf1: m1 and m2, m2 requires public m1
+        // cf1: m1 and m2, m2 requires transitive m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
@@ -397,7 +402,7 @@
         // cf2: m3, m3 requires m2
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -408,8 +413,11 @@
         ClassLoader cl2 = new ClassLoader() { };
         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 
-        assertTrue(layer1.parent().get() == Layer.empty());
-        assertTrue(layer2.parent().get() == layer1);
+        assertTrue(layer1.parents().size() == 1);
+        assertTrue(layer1.parents().get(0) == Layer.empty());
+
+        assertTrue(layer2.parents().size() == 1);
+        assertTrue(layer2.parents().get(0) == layer1);
 
         Module m1 = layer2.findModule("m1").get();
         Module m2 = layer2.findModule("m2").get();
@@ -442,14 +450,14 @@
      *
      * The test consists of three configurations:
      * - Configuration/layer1: m1
-     * - Configuration/layer2: m2 requires public m3, m3 requires m2
+     * - Configuration/layer2: m2 requires transitive m3, m3 requires m2
      */
     public void testImpliedReadabilityWithLayers2() {
 
         // cf1: m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
@@ -460,15 +468,15 @@
         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 
 
-        // cf2: m2, m3: m2 requires public m1, m3 requires m2
+        // cf2: m2, m3: m2 requires transitive m1, m3 requires m2
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -479,8 +487,11 @@
         ClassLoader cl2 = new ClassLoader() { };
         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 
-        assertTrue(layer1.parent().get() == Layer.empty());
-        assertTrue(layer2.parent().get() == layer1);
+        assertTrue(layer1.parents().size() == 1);
+        assertTrue(layer1.parents().get(0) == Layer.empty());
+
+        assertTrue(layer2.parents().size() == 1);
+        assertTrue(layer2.parents().get(0) == layer1);
 
         Module m1 = layer2.findModule("m1").get();
         Module m2 = layer2.findModule("m2").get();
@@ -509,7 +520,7 @@
      *
      * The test consists of three configurations:
      * - Configuration/layer1: m1
-     * - Configuration/layer2: m2 requires public m1
+     * - Configuration/layer2: m2 requires transitive m1
      * - Configuration/layer3: m3 requires m1
      */
     public void testImpliedReadabilityWithLayers3() {
@@ -517,7 +528,7 @@
         // cf1: m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
@@ -528,11 +539,11 @@
         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 
 
-        // cf2: m2 requires public m1
+        // cf2: m2 requires transitive m1
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
@@ -546,7 +557,7 @@
         // cf3: m3 requires m2
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
+            = ModuleDescriptor.module("m3")
                 .requires("m2")
                 .build();
 
@@ -557,9 +568,14 @@
         ClassLoader cl3 = new ClassLoader() { };
         Layer layer3 = layer2.defineModules(cf3, mn -> cl3);
 
-        assertTrue(layer1.parent().get() == Layer.empty());
-        assertTrue(layer2.parent().get() == layer1);
-        assertTrue(layer3.parent().get() == layer2);
+        assertTrue(layer1.parents().size() == 1);
+        assertTrue(layer1.parents().get(0) == Layer.empty());
+
+        assertTrue(layer2.parents().size() == 1);
+        assertTrue(layer2.parents().get(0) == layer1);
+
+        assertTrue(layer3.parents().size() == 1);
+        assertTrue(layer3.parents().get(0) == layer2);
 
         Module m1 = layer3.findModule("m1").get();
         Module m2 = layer3.findModule("m2").get();
@@ -587,20 +603,20 @@
      * Test layers with implied readability.
      *
      * The test consists of two configurations:
-     * - Configuration/layer1: m1, m2 requires public m1
-     * - Configuration/layer2: m3 requires public m2, m4 requires m3
+     * - Configuration/layer1: m1, m2 requires transitive m1
+     * - Configuration/layer2: m3 requires transitive m2, m4 requires m3
      */
     public void testImpliedReadabilityWithLayers4() {
 
-        // cf1: m1, m2 requires public m1
+        // cf1: m1, m2 requires transitive m1
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2")
-                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m1")
+            = ModuleDescriptor.module("m2")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
                 .build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
@@ -611,15 +627,15 @@
         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 
 
-        // cf2: m3 requires public m2, m4 requires m3
+        // cf2: m3 requires transitive m2, m4 requires m3
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3")
-                .requires(ModuleDescriptor.Requires.Modifier.PUBLIC, "m2")
+            = ModuleDescriptor.module("m3")
+                .requires(Set.of(Requires.Modifier.TRANSITIVE), "m2")
                 .build();
 
         ModuleDescriptor descriptor4
-            = new ModuleDescriptor.Builder("m4")
+            = ModuleDescriptor.module("m4")
                 .requires("m3")
                 .build();
 
@@ -631,8 +647,11 @@
         ClassLoader cl2 = new ClassLoader() { };
         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 
-        assertTrue(layer1.parent().get() == Layer.empty());
-        assertTrue(layer2.parent().get() == layer1);
+        assertTrue(layer1.parents().size() == 1);
+        assertTrue(layer1.parents().get(0) == Layer.empty());
+
+        assertTrue(layer2.parents().size() == 1);
+        assertTrue(layer2.parents().get(0) == layer1);
 
         Module m1 = layer2.findModule("m1").get();
         Module m2 = layer2.findModule("m2").get();
@@ -675,7 +694,7 @@
     public void testModuleAlreadyDefinedToLoader() {
 
         ModuleDescriptor md
-            = new ModuleDescriptor.Builder("m")
+            = ModuleDescriptor.module("m")
                 .requires("java.base")
                 .build();
 
@@ -704,14 +723,14 @@
     public void testPackageAlreadyInNamedModule() {
 
         ModuleDescriptor md1
-            = new ModuleDescriptor.Builder("m1")
-                .conceals("p")
+            = ModuleDescriptor.module("m1")
+                .contains("p")
                 .requires("java.base")
                 .build();
 
         ModuleDescriptor md2
-            = new ModuleDescriptor.Builder("m2")
-                .conceals("p")
+            = ModuleDescriptor.module("m2")
+                .contains("p")
                 .requires("java.base")
                 .build();
 
@@ -749,8 +768,8 @@
         assertFalse(c.getModule().isNamed());  // in unnamed module
 
         ModuleDescriptor md
-            = new ModuleDescriptor.Builder("m")
-                .conceals(c.getPackageName())
+            = ModuleDescriptor.module("m")
+                .contains(c.getPackageName())
                 .requires("java.base")
                 .build();
 
@@ -768,7 +787,7 @@
      */
     public void testLayerWithJavaBase() {
         ModuleDescriptor descriptor
-            = new ModuleDescriptor.Builder("java.base")
+            = ModuleDescriptor.module("java.base")
                 .exports("java.lang")
                 .build();
 
@@ -782,12 +801,7 @@
         ClassLoader scl = ClassLoader.getSystemClassLoader();
 
         try {
-            Layer.boot().defineModules(cf, loader -> null );
-            assertTrue(false);
-        } catch (LayerInstantiationException e) { }
-
-        try {
-            Layer.boot().defineModules(cf, loader -> new ClassLoader() { });
+            Layer.boot().defineModules(cf, mn -> new ClassLoader() { });
             assertTrue(false);
         } catch (LayerInstantiationException e) { }
 
@@ -804,13 +818,81 @@
 
 
     /**
+     * Attempt to create a Layer with a module containing a "java." package.
+     * This should only be allowed when the module is defined to the platform
+     * class loader.
+     */
+    @Test(enabled = false)
+    public void testLayerWithJavaPackage() {
+        ModuleDescriptor descriptor
+            = ModuleDescriptor.module("foo")
+                .contains("java.foo")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor);
+
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.of(), Set.of("foo"));
+        assertTrue(cf.modules().size() == 1);
+
+        ClassLoader pcl = ClassLoader.getPlatformClassLoader();
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        try {
+            Layer.boot().defineModules(cf, mn -> new ClassLoader() { });
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+
+        try {
+            Layer.boot().defineModulesWithOneLoader(cf, scl);
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+
+        try {
+            Layer.boot().defineModulesWithManyLoaders(cf, scl);
+            assertTrue(false);
+        } catch (LayerInstantiationException e) { }
+
+        // create layer with module defined to platform class loader
+        Layer layer = Layer.boot().defineModules(cf, mn -> pcl);
+        Optional<Module> om = layer.findModule("foo");
+        assertTrue(om.isPresent());
+        Module foo = om.get();
+        assertTrue(foo.getClassLoader() == pcl);
+        assertTrue(foo.getPackages().length == 1);
+        assertTrue(foo.getPackages()[0].equals("java.foo"));
+    }
+
+
+    /**
+     * Attempt to create a Layer with a module defined to the boot loader
+     */
+    @Test(expectedExceptions = { LayerInstantiationException.class })
+    public void testLayerWithBootLoader() {
+        ModuleDescriptor descriptor
+            = ModuleDescriptor.module("m1")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor);
+
+        Configuration cf = Layer.boot()
+            .configuration()
+            .resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+        assertTrue(cf.modules().size() == 1);
+
+        Layer.boot().defineModules(cf, mn -> null );
+    }
+
+
+    /**
      * Parent of configuration != configuration of parent Layer
      */
     @Test(expectedExceptions = { IllegalArgumentException.class })
     public void testIncorrectParent1() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .requires("java.base")
                 .build();
 
@@ -831,7 +913,7 @@
     public void testIncorrectParent2() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1")
+            = ModuleDescriptor.module("m1")
                 .build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
diff --git a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
index a3305d5..23c7d06 100644
--- a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
+++ b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java
@@ -30,6 +30,8 @@
  * @summary Tests for java.lang.reflect.Layer@createWithXXX methods
  */
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleFinder;
@@ -38,8 +40,10 @@
 import java.lang.reflect.LayerInstantiationException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Module;
+import java.net.URL;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -263,10 +267,10 @@
     public void testOverlappingPackages() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1").exports("p").build();
+            = ModuleDescriptor.module("m1").exports("p").build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2").exports("p").build();
+            = ModuleDescriptor.module("m2").exports("p").build();
 
         ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
 
@@ -297,10 +301,10 @@
     public void testSplitDelegation() {
 
         ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder("m1").exports("p").build();
+            = ModuleDescriptor.module("m1").exports("p").build();
 
         ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder("m2").exports("p").build();
+            = ModuleDescriptor.module("m2").exports("p").build();
 
         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
 
@@ -312,10 +316,10 @@
         checkLayer(layer1, "m1", "m2");
 
         ModuleDescriptor descriptor3
-            = new ModuleDescriptor.Builder("m3").requires("m1").build();
+            = ModuleDescriptor.module("m3").requires("m1").build();
 
         ModuleDescriptor descriptor4
-            = new ModuleDescriptor.Builder("m4").requires("m2").build();
+            = ModuleDescriptor.module("m4").requires("m2").build();
 
         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
 
@@ -568,6 +572,48 @@
     }
 
 
+    /**
+     * Basic test of resource loading with a class loader created by
+     * Layer.defineModulesWithOneLoader.
+     */
+    public void testResourcesOneLoader() throws Exception {
+        Configuration cf = resolveRequires("m1");
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
+        ClassLoader loader = layer.findLoader("m1");
+        testResourceLoading(loader, "p/Main.class");
+    }
+
+    /**
+     * Basic test of resource loading with a class loader created by
+     * Layer.defineModulesWithOneLoader.
+     */
+    public void testResourcesManyLoaders() throws Exception {
+        Configuration cf = resolveRequires("m1");
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl);
+        ClassLoader loader = layer.findLoader("m1");
+        testResourceLoading(loader, "p/Main.class");
+    }
+
+    /**
+     * Test that a resource is located by a class loader.
+     */
+    private void testResourceLoading(ClassLoader loader, String name)
+        throws IOException
+    {
+        URL url = loader.getResource(name);
+        assertNotNull(url);
+
+        try (InputStream in = loader.getResourceAsStream(name)) {
+            assertNotNull(in);
+        }
+
+        Enumeration<URL> urls = loader.getResources(name);
+        assertTrue(urls.hasMoreElements());
+    }
+
+
     // -- supporting methods --
 
 
diff --git a/jdk/test/java/lang/reflect/Layer/LayerControllerTest.java b/jdk/test/java/lang/reflect/Layer/LayerControllerTest.java
new file mode 100644
index 0000000..6582e49
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Layer/LayerControllerTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @build LayerControllerTest ModuleUtils
+ * @run testng LayerControllerTest
+ * @summary Basic tests for java.lang.reflect.Layer.Controller
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.List;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class LayerControllerTest {
+
+    /**
+     * Creates a Controller for a module layer containing modules m1 and m2.
+     * Module m1 contains p1, reads java.base, does not export/open any package
+     * Module m2 contains p2, reads java.base, does not export/open any package
+     */
+    private Layer.Controller createTestLayer() {
+        ModuleDescriptor descriptor1
+            = ModuleDescriptor.module("m1")
+                .contains("p1")
+                .requires("java.base")
+                .build();
+
+        ModuleDescriptor descriptor2
+            = ModuleDescriptor.module("m2")
+                .requires("java.base")
+                .contains("p2")
+                .build();
+
+        ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
+        Layer bootLayer = Layer.boot();
+
+        Configuration cf = bootLayer.configuration()
+                .resolveRequires(finder, ModuleFinder.of(), Set.of("m1", "m2"));
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        Layer.Controller controller
+                = Layer.defineModulesWithOneLoader(cf, List.of(bootLayer), scl);
+
+        Layer layer = controller.layer();
+
+        assertTrue(layer.modules().size() == 2);
+        assertTrue(layer.findModule("m1").isPresent());
+        assertTrue(layer.findModule("m2").isPresent());
+
+        return controller;
+    }
+
+    /**
+     * Basic test of Layer.Controller to update modules m1 and m2 to read and
+     * open packages to each other.
+     */
+    public void testBasic() {
+        Layer.Controller controller = createTestLayer();
+        Layer layer = controller.layer();
+        Module m1 = layer.findModule("m1").orElseThrow(RuntimeException::new);
+        Module m2 = layer.findModule("m2").orElseThrow(RuntimeException::new);
+
+        assertFalse(m1.canRead(m2));
+        assertFalse(m1.isExported("p1"));
+        assertFalse(m1.isOpen("p1"));
+        assertFalse(m1.isExported("p1", m2));
+        assertFalse(m1.isOpen("p1", m2));
+
+        assertFalse(m2.canRead(m1));
+        assertFalse(m2.isExported("p2"));
+        assertFalse(m2.isOpen("p2"));
+        assertFalse(m2.isExported("p2", m1));
+        assertFalse(m2.isOpen("p2", m1));
+
+        // update m1 to read m2
+        assertTrue(controller.addReads(m1, m2) == controller);
+        assertTrue(m1.canRead(m2));
+        assertFalse(m2.canRead(m1));
+
+        // update m2 to read m1
+        assertTrue(controller.addReads(m2, m1) == controller);
+        assertTrue(m1.canRead(m2));
+        assertTrue(m1.canRead(m1));
+
+        // update m1 to open p1 to m2
+        assertTrue(controller.addOpens(m1, "p1", m2) == controller);
+        assertTrue(m1.isExported("p1", m2));
+        assertTrue(m1.isOpen("p1", m2));
+        assertFalse(m1.isExported("p1"));
+        assertFalse(m1.isOpen("p1"));
+
+        // update m2 to open p2 to m1
+        assertTrue(controller.addOpens(m2, "p2", m1) == controller);
+        assertTrue(m2.isExported("p2", m1));
+        assertTrue(m2.isOpen("p2", m1));
+        assertFalse(m2.isExported("p2"));
+        assertFalse(m2.isOpen("p2"));
+    }
+
+    /**
+     * Test invalid argument handling
+     */
+    public void testBadArguments() {
+        Layer.Controller controller = createTestLayer();
+        Layer layer = controller.layer();
+        Module m1 = layer.findModule("m1").orElseThrow(RuntimeException::new);
+        Module m2 = layer.findModule("m2").orElseThrow(RuntimeException::new);
+        Module base = Object.class.getModule();
+
+        // java.base is not in layer
+        try {
+            controller.addReads(base, m2);
+            assertTrue(false);
+        } catch (IllegalArgumentException expected) { }
+
+        // java.base is not in layer
+        try {
+            controller.addOpens(base, "java.lang", m2);
+            assertTrue(false);
+        } catch (IllegalArgumentException expected) { }
+
+        // m1 does not contain java.lang
+        try {
+            controller.addOpens(m1, "java.lang", m2);
+            assertTrue(false);
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    /**
+     * Test null handling
+     */
+    public void testNulls() {
+        Layer.Controller controller = createTestLayer();
+        Layer layer = controller.layer();
+        Module m1 = layer.findModule("m1").orElseThrow(RuntimeException::new);
+        Module m2 = layer.findModule("m2").orElseThrow(RuntimeException::new);
+        assertTrue(m1 != null);
+        assertTrue(m2 != null);
+
+        try {
+            controller.addReads(null, m2);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            controller.addReads(m1, null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            controller.addOpens(null, "p1", m2);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            controller.addOpens(m1, null, m2);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+
+        try {
+            controller.addOpens(m1, "p1", null);
+            assertTrue(false);
+        } catch (NullPointerException expected) { }
+    }
+}
\ No newline at end of file
diff --git a/jdk/test/java/lang/reflect/Module/AnnotationsTest.java b/jdk/test/java/lang/reflect/Module/AnnotationsTest.java
new file mode 100644
index 0000000..1746d6d
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/AnnotationsTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import jdk.internal.module.ClassFileAttributes;
+import jdk.internal.org.objectweb.asm.AnnotationVisitor;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.base/jdk.internal.module
+ *          java.xml
+ * @run testng AnnotationsTest
+ * @summary Basic test of annotations on modules
+ */
+
+public class AnnotationsTest {
+
+    /**
+     * Test that there are no annotations on an unnamed module.
+     */
+    @Test
+    public void testUnnamedModule() {
+        Module module = this.getClass().getModule();
+        assertTrue(module.getAnnotations().length == 0);
+    }
+
+    /**
+     * Test loading a module with a RuntimeVisibleAnnotation attribute.
+     * The test copies the module-info.class for java.xml, adds the attribute,
+     * and then loads the updated module.
+     */
+    @Test
+    public void testNamedModule() throws IOException {
+
+        // "deprecate" java.xml
+        Path dir = Files.createTempDirectory("mods");
+        deprecateModule("java.xml", true, "9", dir);
+
+        // "load" the cloned java.xml
+        Module module = loadModule(dir, "java.xml");
+
+        // check the annotation is present
+        assertTrue(module.isAnnotationPresent(Deprecated.class));
+        Deprecated d = module.getAnnotation(Deprecated.class);
+        assertNotNull(d, "@Deprecated not found");
+        assertTrue(d.forRemoval());
+        assertEquals(d.since(), "9");
+        Annotation[] a = module.getAnnotations();
+        assertTrue(a.length == 1);
+        assertTrue(a[0] instanceof Deprecated);
+    }
+
+
+    /**
+     * Copy the module-info.class for the given module, add the
+     * Deprecated annotation, and write the updated module-info.class
+     * to a directory.
+     */
+    static void deprecateModule(String name,
+                                boolean forRemoval,
+                                String since,
+                                Path output) throws IOException {
+        Module module = Layer.boot().findModule(name).orElse(null);
+        assertNotNull(module, name + " not found");
+
+        InputStream in = module.getResourceAsStream("module-info.class");
+        assertNotNull(in, "No module-info.class for " + name);
+
+        try (in) {
+            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+                                             + ClassWriter.COMPUTE_FRAMES);
+
+            ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) { };
+
+            ClassReader cr = new ClassReader(in);
+
+            List<Attribute> attrs = new ArrayList<>();
+            attrs.add(new ClassFileAttributes.ModuleAttribute());
+            attrs.add(new ClassFileAttributes.ModulePackagesAttribute());
+            attrs.add(new ClassFileAttributes.ModuleVersionAttribute());
+            attrs.add(new ClassFileAttributes.ModuleTargetAttribute());
+            cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
+
+            AnnotationVisitor annotationVisitor
+                = cv.visitAnnotation("Ljava/lang/Deprecated;", true);
+            annotationVisitor.visit("forRemoval", forRemoval);
+            annotationVisitor.visit("since", since);
+            annotationVisitor.visitEnd();
+
+            byte[] bytes = cw.toByteArray();
+            Path mi = output.resolve("module-info.class");
+            Files.write(mi, bytes);
+        }
+    }
+
+    /**
+     * Load the module of the given name in the given directory into a
+     * child layer.
+     */
+    static Module loadModule(Path dir, String name) throws IOException {
+        ModuleFinder finder = ModuleFinder.of(dir);
+
+        Layer bootLayer = Layer.boot();
+
+        Configuration cf = bootLayer.configuration()
+                .resolveRequires(finder, ModuleFinder.of(), Set.of(name));
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+
+        Module module = layer.findModule(name).orElse(null);
+        assertNotNull(module, name + " not loaded");
+        return module;
+    }
+}
diff --git a/jdk/test/java/lang/reflect/Module/BasicModuleTest.java b/jdk/test/java/lang/reflect/Module/BasicModuleTest.java
index 32a945a5..bafa57b 100644
--- a/jdk/test/java/lang/reflect/Module/BasicModuleTest.java
+++ b/jdk/test/java/lang/reflect/Module/BasicModuleTest.java
@@ -174,8 +174,24 @@
         // isExported
         assertTrue(base.isExported("java.lang"));
         assertTrue(base.isExported("java.lang", thisModule));
+        assertTrue(base.isExported("java.lang", base));
+        assertFalse(base.isExported("jdk.internal.misc"));
+        assertFalse(base.isExported("jdk.internal.misc", thisModule));
+        assertTrue(base.isExported("jdk.internal.misc", base));
         assertFalse(base.isExported("java.wombat"));
         assertFalse(base.isExported("java.wombat", thisModule));
+        assertFalse(base.isExported("java.wombat", base));
+
+        // isOpen
+        assertFalse(base.isOpen("java.lang"));
+        assertFalse(base.isOpen("java.lang", thisModule));
+        assertTrue(base.isOpen("java.lang", base));
+        assertFalse(base.isOpen("jdk.internal.misc"));
+        assertFalse(base.isOpen("jdk.internal.misc", thisModule));
+        assertTrue(base.isOpen("jdk.internal.misc", base));
+        assertFalse(base.isOpen("java.wombat"));
+        assertFalse(base.isOpen("java.wombat", thisModule));
+        assertFalse(base.isOpen("java.wombat", base));
     }
 
 
diff --git a/jdk/test/java/lang/reflect/Module/WithSecurityManager.java b/jdk/test/java/lang/reflect/Module/WithSecurityManager.java
index 9c95fee..dfb6b76 100644
--- a/jdk/test/java/lang/reflect/Module/WithSecurityManager.java
+++ b/jdk/test/java/lang/reflect/Module/WithSecurityManager.java
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @modules java.logging
+ * @modules jdk.compiler
  * @summary Test java.lang.reflect.Module methods that specify permission checks
  * @run main/othervm -Djava.security.policy=${test.src}/allow.policy WithSecurityManager allow
  * @run main/othervm WithSecurityManager deny
@@ -47,8 +47,8 @@
 public class WithSecurityManager {
 
     // a module that will be loaded into a child layer
-    static final String ANOTHER_MODULE          = "java.logging";
-    static final String ANOTHER_MODULE_RESOURCE = "java/util/logging/Logger.class";
+    static final String ANOTHER_MODULE          = "jdk.compiler";
+    static final String ANOTHER_MODULE_RESOURCE = "com/sun/tools/javac/Main.class";
 
     public static void main(String[] args) throws IOException {
         boolean allow = args[0].equals("allow");
@@ -144,4 +144,4 @@
             throw new RuntimeException();
     }
 
-}
\ No newline at end of file
+}
diff --git a/jdk/test/java/lang/reflect/Module/access/AccessTest.java b/jdk/test/java/lang/reflect/Module/access/AccessTest.java
index 1e6e98a..4bd3f2b 100644
--- a/jdk/test/java/lang/reflect/Module/access/AccessTest.java
+++ b/jdk/test/java/lang/reflect/Module/access/AccessTest.java
@@ -38,8 +38,8 @@
  * @modules jdk.compiler
  * @build AccessTest CompilerUtils jdk.testlibrary.*
  * @run testng AccessTest
- * @summary Driver for test that checks access to public members in exported
- *          and non-exported packages.
+ * @summary Driver for test that checks access to access to types in
+ *          exported and non-exported packages.
  */
 
 @Test
@@ -74,6 +74,7 @@
         int exitValue
             = executeTestJava("--module-path", MODS_DIR.toString(),
                               "--add-modules", "target",
+                              "-Dsun.reflect.enableStrictMode=true",
                               "-m", "test/test.Main")
                 .outputTo(System.out)
                 .errorTo(System.out)
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/module-info.java b/jdk/test/java/lang/reflect/Module/access/src/target/module-info.java
index 9c987c7..dfca720 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/target/module-info.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/module-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,5 +22,6 @@
  */
 
 module target {
-    exports p;
+    exports p1;
+    exports p2;
 }
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/p/Exported.java b/jdk/test/java/lang/reflect/Module/access/src/target/p/Exported.java
deleted file mode 100644
index 73bdb34..0000000
--- a/jdk/test/java/lang/reflect/Module/access/src/target/p/Exported.java
+++ /dev/null
@@ -1,43 +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 p;
-
-public class Exported {
-
-    /**
-     * Public constructor
-     */
-    public Exported() { }
-
-    /**
-     * Public field
-     */
-    public static Object field;
-
-    /**
-     * Public method
-     */
-    public static void run() {
-    }
-}
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/p/Helper.java b/jdk/test/java/lang/reflect/Module/access/src/target/p1/Helper.java
similarity index 76%
rename from jdk/test/java/lang/reflect/Module/access/src/target/p/Helper.java
rename to jdk/test/java/lang/reflect/Module/access/src/target/p1/Helper.java
index b834364..e0e45e8 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/target/p/Helper.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/p1/Helper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,14 +21,22 @@
  * questions.
  */
 
-package p;
+package p1;
 
 import java.lang.reflect.Module;
 
+/**
+ * Helper class in target module to allow test invoke addExports[Private]
+ */
+
 public class Helper {
     Helper() { }
 
-    public static void exportPackage(String pn, Module who) {
+    public static void addExports(String pn, Module who) {
         Helper.class.getModule().addExports(pn, who);
     }
+
+    public static void addOpens(String pn, Module who) {
+        Helper.class.getModule().addOpens(pn, who);
+    }
 }
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java b/jdk/test/java/lang/reflect/Module/access/src/target/p1/Public.java
similarity index 68%
copy from jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
copy to jdk/test/java/lang/reflect/Module/access/src/target/p1/Public.java
index f0dabdd1..8ee138b 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/p1/Public.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,23 +21,25 @@
  * questions.
  */
 
-package q;
+package p1;
 
-public class Internal {
+public class Public {
 
-    /**
-     * Public constructor
-     */
-    public Internal() { }
+    // public constructor
+    public Public() { }
 
-    /**
-     * Public field
-     */
-    public static Object field;
+    // non-public constructor
+    private Public(Void ignore) { }
 
-    /**
-     * Public method
-     */
-    public static void run() {
-    }
+    // public field
+    public static Object f1;
+
+    // non-public field
+    private static Object f2;
+
+    // public method
+    public static void foo() { }
+
+    // non-public method
+    private static void bar() { }
 }
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java b/jdk/test/java/lang/reflect/Module/access/src/target/p2/NonPublic.java
similarity index 68%
copy from jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
copy to jdk/test/java/lang/reflect/Module/access/src/target/p2/NonPublic.java
index f0dabdd1..5b5d120 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/p2/NonPublic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,23 +21,25 @@
  * questions.
  */
 
-package q;
+package p2;
 
-public class Internal {
+class NonPublic {
 
-    /**
-     * Public constructor
-     */
-    public Internal() { }
+    // public constructor
+    public NonPublic() { }
 
-    /**
-     * Public field
-     */
-    public static Object field;
+    // non-public constructor
+    private NonPublic(Void ignore) { }
 
-    /**
-     * Public method
-     */
-    public static void run() {
-    }
+    // public field
+    public static Object f1;
+
+    // non-public field
+    private static Object f2;
+
+    // public method
+    public static void foo() { }
+
+    // non-public method
+    private static void bar() { }
 }
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java b/jdk/test/java/lang/reflect/Module/access/src/target/q1/Public.java
similarity index 68%
rename from jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
rename to jdk/test/java/lang/reflect/Module/access/src/target/q1/Public.java
index f0dabdd1..85ff95b 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/q1/Public.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,23 +21,25 @@
  * questions.
  */
 
-package q;
+package q1;
 
-public class Internal {
+public class Public {
 
-    /**
-     * Public constructor
-     */
-    public Internal() { }
+    // public constructor
+    public Public() { }
 
-    /**
-     * Public field
-     */
-    public static Object field;
+    // non-public constructor
+    private Public(Void ignore) { }
 
-    /**
-     * Public method
-     */
-    public static void run() {
-    }
+    // public field
+    public static Object f1;
+
+    // non-public field
+    private static Object f2;
+
+    // public method
+    public static void foo() { }
+
+    // non-public method
+    private static void bar() { }
 }
diff --git a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java b/jdk/test/java/lang/reflect/Module/access/src/target/q2/NonPublic.java
similarity index 68%
copy from jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
copy to jdk/test/java/lang/reflect/Module/access/src/target/q2/NonPublic.java
index f0dabdd1..78cba18 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/target/q/Internal.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/target/q2/NonPublic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,23 +21,25 @@
  * questions.
  */
 
-package q;
+package q2;
 
-public class Internal {
+class NonPublic {
 
-    /**
-     * Public constructor
-     */
-    public Internal() { }
+    // public constructor
+    public NonPublic() { }
 
-    /**
-     * Public field
-     */
-    public static Object field;
+    // non-public constructor
+    private NonPublic(Void ignore) { }
 
-    /**
-     * Public method
-     */
-    public static void run() {
-    }
+    // public field
+    public static Object f1;
+
+    // non-public field
+    private static Object f2;
+
+    // public method
+    public static void foo() { }
+
+    // non-public method
+    private static void bar() { }
 }
diff --git a/jdk/test/java/lang/reflect/Module/access/src/test/test/Main.java b/jdk/test/java/lang/reflect/Module/access/src/test/test/Main.java
index 0ba28a7..c58b8e2 100644
--- a/jdk/test/java/lang/reflect/Module/access/src/test/test/Main.java
+++ b/jdk/test/java/lang/reflect/Module/access/src/test/test/Main.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,166 +23,351 @@
 
 package test;
 
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.lang.reflect.InaccessibleObjectException;
 import java.lang.reflect.Layer;
 import java.lang.reflect.Method;
 import java.lang.reflect.Module;
-import java.util.Optional;
 
 /**
- * Test access to public members in exported and non-exported packages.
+ * Test access to public/non-public members of public/non-public classes in
+ * exported and non-exported packages.
  */
 
 public class Main {
 
     public static void main(String[] args) throws Exception {
+        testPublicClassInExportedPackage();
+        testNonPublicClassInExportedPackage();
+        testPublicClassInNonExportedPackage();
+        testNonPublicClassInNonExportedPackage();
+    }
 
+    static void testPublicClassInExportedPackage() throws Exception {
         Module thisModule = Main.class.getModule();
-        assertTrue(thisModule.isNamed());
+        Module targetModule = getTargetModule();
 
-        Optional<Module> om = Layer.boot().findModule("target");
-        assertTrue(om.isPresent());
+        assertTrue(targetModule.isExported("p1"));
+        assertTrue(targetModule.isExported("p1", thisModule));
+        assertTrue(targetModule.isExported("p1", targetModule));
 
-        Module target = om.get();
+        assertFalse(targetModule.isOpen("p1"));
+        assertFalse(targetModule.isOpen("p1", thisModule));
+        assertTrue(targetModule.isOpen("p1", targetModule));
 
-        assertTrue(target.isExported("p"));
-        assertTrue(target.isExported("p", thisModule));
+        Class<?> clazz = Class.forName("p1.Public");
+        Constructor<?> ctor1 = clazz.getConstructor();   // public
+        Constructor<?> ctor2 = clazz.getDeclaredConstructor(Void.class); // non-public
 
-        assertFalse(target.isExported("q"));
-        assertFalse(target.isExported("q", thisModule));
+        Field f1 = clazz.getField("f1");    // public
+        Field f2 = clazz.getDeclaredField("f2");    // non-public
 
+        Method m1 = clazz.getMethod("foo");  // public
+        Method m2 = clazz.getDeclaredMethod("bar");  // non-public
 
-        // thisModule does not read the target module
+        tryAccessConstructor(ctor1, true);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, true);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, true);
+        tryAccessObjectField(f2, false);
 
-        assertFalse(thisModule.canRead(target));
+        trySetAccessible(ctor1, true);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, true);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, true);
+        trySetAccessible(f2, false);
 
-        tryAccessPublicMembers("p.Exported", true);
-        tryAccessPublicMembers("q.Internal", false);
+        targetAddOpens("p1", thisModule);
 
+        tryAccessConstructor(ctor1, true);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, true);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, true);
+        tryAccessObjectField(f2, false);
 
+        trySetAccessible(ctor1, true);
+        trySetAccessible(ctor2, true);
+        trySetAccessible(m1, true);
+        trySetAccessible(m2, true);
+        trySetAccessible(f1, true);
+        trySetAccessible(f2, true);
+    }
 
-        // thisModule reads the target module
+    static void testNonPublicClassInExportedPackage() throws Exception {
+        Module thisModule = Main.class.getModule();
+        Module targetModule = getTargetModule();
 
-        thisModule.addReads(target);
-        assertTrue(thisModule.canRead(target));
+        assertTrue(targetModule.isExported("p2"));
+        assertTrue(targetModule.isExported("p2", thisModule));
+        assertTrue(targetModule.isExported("p2", targetModule));
 
-        tryAccessPublicMembers("p.Exported", true);
-        tryAccessPublicMembers("q.Internal", false);
+        assertFalse(targetModule.isOpen("p2"));
+        assertFalse(targetModule.isOpen("p2", thisModule));
+        assertTrue(targetModule.isOpen("p1", targetModule));
 
+        Class<?> clazz = Class.forName("p2.NonPublic");
+        Constructor<?> ctor1 = clazz.getConstructor();
+        Constructor<?> ctor2 = clazz.getDeclaredConstructor(Void.class);
 
+        Field f1 = clazz.getField("f1");    // public
+        Field f2 = clazz.getDeclaredField("f2");    // non-public
 
-        // change target module to export its internal package to thisModule
+        Method m1 = clazz.getMethod("foo");  // public
+        Method m2 = clazz.getDeclaredMethod("bar");  // non-public
 
-        targetAddExports("q", thisModule);
-        assertFalse(target.isExported("q"));
-        assertTrue(target.isExported("q", thisModule));
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
 
-        tryAccessPublicMembers("p.Exported", true);
-        tryAccessPublicMembers("q.Internal", true);
+        trySetAccessible(ctor1, false);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, false);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, false);
+        trySetAccessible(f2, false);
+
+        targetAddExports("p2", thisModule);
+
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, false);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, false);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, false);
+        trySetAccessible(f2, false);
+
+        targetAddOpens("p2", thisModule);
+
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, true);
+        trySetAccessible(ctor2, true);
+        trySetAccessible(m1, true);
+        trySetAccessible(m2, true);
+        trySetAccessible(f1, true);
+        trySetAccessible(f2, true);
+    }
+
+    static void testPublicClassInNonExportedPackage() throws Exception {
+        Module thisModule = Main.class.getModule();
+        Module targetModule = getTargetModule();
+
+        assertFalse(targetModule.isExported("q1"));
+        assertFalse(targetModule.isExported("q1", thisModule));
+        assertTrue(targetModule.isExported("q1", targetModule));
+
+        assertFalse(targetModule.isOpen("q1"));
+        assertFalse(targetModule.isOpen("q1", thisModule));
+        assertTrue(targetModule.isOpen("q1", targetModule));
+
+        Class<?> clazz = Class.forName("q1.Public");
+        Constructor<?> ctor1 = clazz.getConstructor();  // public
+        Constructor<?> ctor2 = clazz.getDeclaredConstructor(Void.class);  // non-public
+
+        Field f1 = clazz.getField("f1");    // public
+        Field f2 = clazz.getDeclaredField("f2");    // non-public
+
+        Method m1 = clazz.getMethod("foo");  // public
+        Method m2 = clazz.getDeclaredMethod("bar");  // non-public
+
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, false);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, false);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, false);
+        trySetAccessible(f2, false);
+
+        targetAddExports("q1", thisModule);
+
+        tryAccessConstructor(ctor1, true);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, true);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, true);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, true);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, true);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, true);
+        trySetAccessible(f2, false);
+
+        targetAddOpens("q1", thisModule);
+
+        tryAccessConstructor(ctor1, true);
+        tryAccessConstructor(ctor1, false);
+        tryAccessMethod(m1, true);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, true);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, true);
+        trySetAccessible(ctor2, true);
+        trySetAccessible(m1, true);
+        trySetAccessible(m2, true);
+        trySetAccessible(f1, true);
+        trySetAccessible(f2, true);
+    }
+
+    static void testNonPublicClassInNonExportedPackage() throws Exception {
+        Module thisModule = Main.class.getModule();
+        Module targetModule = getTargetModule();
+
+        assertFalse(targetModule.isExported("q2"));
+        assertFalse(targetModule.isExported("q2", thisModule));
+        assertTrue(targetModule.isExported("q2", targetModule));
+
+        assertFalse(targetModule.isOpen("q2"));
+        assertFalse(targetModule.isOpen("q2", thisModule));
+        assertTrue(targetModule.isOpen("q2", targetModule));
+
+        Class<?> clazz = Class.forName("q2.NonPublic");
+        Constructor<?> ctor1 = clazz.getConstructor();  // public
+        Constructor<?> ctor2 = clazz.getDeclaredConstructor(Void.class);  // non-public
+
+        Field f1 = clazz.getField("f1");    // public
+        Field f2 = clazz.getDeclaredField("f2");    // non-public
+
+        Method m1 = clazz.getMethod("foo");  // public
+        Method m2 = clazz.getDeclaredMethod("bar");  // non-public
+
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, false);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, false);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, false);
+        trySetAccessible(f2, false);
+
+        targetAddExports("q2", thisModule);
+
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, false);
+        trySetAccessible(ctor2, false);
+        trySetAccessible(m1, false);
+        trySetAccessible(m2, false);
+        trySetAccessible(f1, false);
+        trySetAccessible(f2, false);
+
+        targetAddOpens("q2", thisModule);
+
+        tryAccessConstructor(ctor1, false);
+        tryAccessConstructor(ctor2, false);
+        tryAccessMethod(m1, false);
+        tryAccessMethod(m2, false);
+        tryAccessObjectField(f1, false);
+        tryAccessObjectField(f2, false);
+
+        trySetAccessible(ctor1, true);
+        trySetAccessible(m1, true);
+        trySetAccessible(m2, true);
+        trySetAccessible(f1, true);
+        trySetAccessible(f2, true);
     }
 
 
-    /**
-     * Attempt to access public members in a target class.
-     */
-    static void tryAccessPublicMembers(String cn, boolean shouldSucceed)
-        throws Exception
-    {
+    static Module getTargetModule() {
+        return Layer.boot().findModule("target").get();
+    }
 
-        Class<?> clazz = Class.forName(cn);
-
-        Module thisModule = Main.class.getModule();
-        Module targetModule = clazz.getModule();
-
-        // check if the target class is in an exported package
-        String pn = cn.substring(0, cn.lastIndexOf('.'));
-        boolean exported = targetModule.isExported(pn, thisModule);
-        assertTrue(exported == shouldSucceed);
-        boolean shouldFail = !shouldSucceed;
-
-
-        // Class.newInstance
-
-        try {
-            clazz.newInstance();
-            assertTrue(shouldSucceed);
-        } catch (IllegalAccessException e) {
-            assertTrue(shouldFail);
-        }
-
-
-        // Constructor.newInstance and Constructor.setAccessible
-
-        Constructor<?> ctor = clazz.getConstructor();
+    static void tryAccessConstructor(Constructor<?> ctor, boolean shouldSucceed) {
         try {
             ctor.newInstance();
             assertTrue(shouldSucceed);
-        } catch (IllegalAccessException e) {
-            assertTrue(shouldFail);
+        } catch (Exception e) {
+            assertFalse(shouldSucceed);
         }
+    }
+
+    static void tryAccessMethod(Method method, boolean shouldSucceed) {
         try {
-            ctor.setAccessible(true);
+            method.invoke(null);
             assertTrue(shouldSucceed);
-            ctor.newInstance();
-        } catch (InaccessibleObjectException e) {
-            assertTrue(shouldFail);
+        } catch (Exception e) {
+            e.printStackTrace();
+            assertFalse(shouldSucceed);
         }
+    }
 
-
-        // Method.invoke and Method.setAccessible
-
-        Method m = clazz.getDeclaredMethod("run");
-        try {
-            m.invoke(null);
-            assertTrue(shouldSucceed);
-        } catch (IllegalAccessException e) {
-            assertTrue(shouldFail);
-        }
-        try {
-            m.setAccessible(true);
-            assertTrue(shouldSucceed);
-            m.invoke(null);
-        } catch (InaccessibleObjectException e) {
-            assertTrue(shouldFail);
-        }
-
-        // Field.get, Field.set and Field.setAccessible
-
-        Field f = clazz.getDeclaredField("field");
+    static void tryAccessObjectField(Field f, boolean shouldSucceed) {
         try {
             f.get(null);
             assertTrue(shouldSucceed);
-        } catch (IllegalAccessException e) {
-            assertTrue(shouldFail);
+        } catch (Exception e) {
+            assertFalse(shouldSucceed);
         }
         try {
-            f.set(null, 100);
+            f.set(null, new Object());
             assertTrue(shouldSucceed);
-        } catch (IllegalAccessException e) {
-            assertTrue(shouldFail);
+        } catch (Exception e) {
+            assertFalse(shouldSucceed);
         }
-        try {
-            f.setAccessible(true);
-            f.get(null);
-            f.set(null, 100);
-            assertTrue(shouldSucceed);
-        } catch (InaccessibleObjectException e) {
-            assertTrue(shouldFail);
-        }
+    }
 
+    static void trySetAccessible(AccessibleObject ao, boolean shouldSucceed) {
+        try {
+            ao.setAccessible(true);
+            assertTrue(shouldSucceed);
+        } catch (Exception e) {
+            assertFalse(shouldSucceed);
+        }
     }
 
     /**
      * Update target module to export a package to the given module.
      */
     static void targetAddExports(String pn, Module who) throws Exception {
-        Class<?> helper = Class.forName("p.Helper");
-        Method m = helper.getMethod("exportPackage", String.class, Module.class);
+        Class<?> helper = Class.forName("p1.Helper");
+        Method m = helper.getMethod("addExports", String.class, Module.class);
         m.invoke(null, pn, who);
     }
 
+    /**
+     * Update target module to open a package to the given module.
+     */
+    static void targetAddOpens(String pn, Module who) throws Exception {
+        Class<?> helper = Class.forName("p1.Helper");
+        Method m = helper.getMethod("addOpens", String.class, Module.class);
+        m.invoke(null, pn, who);
+    }
 
     static void assertTrue(boolean expr) {
         if (!expr) throw new RuntimeException();
diff --git a/jdk/test/java/lang/reflect/Module/annotation/Basic.java b/jdk/test/java/lang/reflect/Module/annotation/Basic.java
new file mode 100644
index 0000000..4373378
--- /dev/null
+++ b/jdk/test/java/lang/reflect/Module/annotation/Basic.java
@@ -0,0 +1,77 @@
+/*
+ * 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
+ * @library src
+ * @build m/* Basic
+ * @run testng/othervm Basic
+ * @summary Basic test for annotations on modules
+ */
+
+import java.lang.reflect.Module;
+import java.util.Arrays;
+
+import p.annotation.Foo;
+import p.annotation.Bar;
+import p.annotation.Baz;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class Basic {
+
+    final Module module = Foo.class.getModule();
+
+    /**
+     * {@code @Foo} does not have RUNTIME retention policy.
+     */
+    @Test
+    public void testInvisibleAnnotation() {
+        assertFalse(module.isAnnotationPresent(Foo.class));
+        assertNull(module.getAnnotation(Foo.class));
+    }
+
+    /**
+     * {@code @Bar} has RUNTIME retention policy and value "bar"
+     */
+    @Test
+    public void testBarAnnotation() {
+        assertTrue(module.isAnnotationPresent(Bar.class));
+        Bar bar = module.getAnnotation(Bar.class);
+        assertNotNull(bar);
+        assertEquals(bar.value(), "bar");
+    }
+
+    /**
+     * {@code @Baz} has RUNTIME retention policy has a repeating value
+     */
+    @Test
+    public void testBazAnnotation() {
+        assertTrue(module.isAnnotationPresent(Baz.class));
+        Baz baz = module.getAnnotation(Baz.class);
+        assertNotNull(baz);
+        String[] expected = { "one", "two", "three" };
+        assertTrue(Arrays.equals(baz.value(), expected));
+    }
+}
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/jdk/test/java/lang/reflect/Module/annotation/src/m/module-info.java
similarity index 90%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to jdk/test/java/lang/reflect/Module/annotation/src/m/module-info.java
index 4c3b290..e6cb17c 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/jdk/test/java/lang/reflect/Module/annotation/src/m/module-info.java
@@ -21,9 +21,11 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+import p.annotation.*;
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+@Foo
+@Bar("bar")
+@Baz({"one", "two", "three"})
+module m {
+    exports p.annotation;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Bar.java
similarity index 77%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Bar.java
index 789cdb9..c6d48a3 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Bar.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package p.annotation;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
-    }
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.MODULE;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value={MODULE})
+public @interface Bar {
+   String value();
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Baz.java
similarity index 77%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Baz.java
index 789cdb9..887e616 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Baz.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package p.annotation;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
-    }
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.MODULE;
+
+@Target(value={MODULE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Baz {
+   String[] value();
 }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Foo.java
similarity index 85%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Foo.java
index 242f168..c1075c7 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/lang/reflect/Module/annotation/src/m/p/annotation/Foo.java
@@ -21,5 +21,10 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package p.annotation;
+
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.MODULE;
+
+@Target(value={MODULE})
+public @interface Foo {}
diff --git a/jdk/test/java/lang/reflect/Proxy/src/m3/module-info.java b/jdk/test/java/lang/reflect/Proxy/src/m3/module-info.java
index cf4da7c..a772b41 100644
--- a/jdk/test/java/lang/reflect/Proxy/src/m3/module-info.java
+++ b/jdk/test/java/lang/reflect/Proxy/src/m3/module-info.java
@@ -22,6 +22,6 @@
  */
 
 module m3 {
-    requires public m2;
+    requires transitive m2;
     exports p.three;
 }
diff --git a/jdk/test/java/lang/reflect/Proxy/src/test/module-info.java b/jdk/test/java/lang/reflect/Proxy/src/test/module-info.java
index 75c2d33..5e63632 100644
--- a/jdk/test/java/lang/reflect/Proxy/src/test/module-info.java
+++ b/jdk/test/java/lang/reflect/Proxy/src/test/module-info.java
@@ -23,7 +23,7 @@
 
 module test {
     requires m1;
-    requires m3;   // requires public m2
+    requires m3;   // requires transitive m2
 
     exports jdk.test;
 }
diff --git a/jdk/test/java/net/Authenticator/B4933582.java b/jdk/test/java/net/Authenticator/B4933582.java
index ac87062..f8b89ae 100644
--- a/jdk/test/java/net/Authenticator/B4933582.java
+++ b/jdk/test/java/net/Authenticator/B4933582.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,6 +21,15 @@
  * questions.
  */
 
+/*
+ * @test
+ * @bug 4933582
+ * @library ../../../sun/net/www/httptest
+ * @modules java.base/sun.net.www
+ *          java.base/sun.net.www.protocol.http
+ * @build HttpCallback HttpTransaction TestHttpServer B4933582
+ * @run main/othervm B4933582
+ */
 import java.io.*;
 import java.net.*;
 import java.util.*;
@@ -44,7 +53,7 @@
         req.orderlyClose();
     }
 
-    static boolean firstTime = true;
+    static volatile boolean firstTime = true;
 
     public void request (HttpTransaction req) {
         try {
@@ -114,43 +123,67 @@
         URL url = new URL (u);
         System.out.println ("client opening connection to: " + u);
         URLConnection urlc = url.openConnection ();
-        InputStream is = urlc.getInputStream ();
-        read (is);
-        is.close();
+        try(InputStream is = urlc.getInputStream ()) {
+            read (is);
+        }
     }
 
     static TestHttpServer server;
 
     public static void main (String[] args) throws Exception {
-        firstTime = args[0].equals ("first");
         MyAuthenticator auth = new MyAuthenticator ();
         Authenticator.setDefault (auth);
         CacheImpl cache;
         try {
-            if (firstTime) {
-                server = new TestHttpServer (new B4933582(), 1, 10, 0);
-                cache = new CacheImpl (server.getLocalPort());
-            } else {
-                cache = new CacheImpl ();
-                server = new TestHttpServer(new B4933582(), 1, 10, cache.getPort());
-            }
+            server = new TestHttpServer (new B4933582(), 1, 10, 0);
+            cache = new CacheImpl (server.getLocalPort());
             AuthCacheValue.setAuthCache (cache);
-            System.out.println ("Server: listening on port: " + server.getLocalPort());
             client ("http://localhost:"+server.getLocalPort()+"/d1/foo.html");
-        } catch (Exception e) {
+        } finally {
             if (server != null) {
                 server.terminate();
             }
-            throw e;
         }
+
         int f = auth.getCount();
-        if (firstTime && f != 1) {
-            except ("Authenticator was called "+f+" times. Should be 1");
+        if (f != 1) {
+            except("Authenticator was called " + f + " times. Should be 1");
         }
-        if (!firstTime && f != 0) {
-            except ("Authenticator was called "+f+" times. Should be 0");
+
+        firstTime = false;
+
+        int retries = 0;
+        cache = new CacheImpl();
+        while (true) {
+            try {
+                server = new TestHttpServer(new B4933582(), 1, 10,
+                        cache.getPort());
+                break;
+            } catch (BindException e) {
+                if (retries++ < 5) {
+                    Thread.sleep(200L);
+                    System.out.println("BindException \"" + e.getMessage()
+                            + "\", retrying...");
+                    continue;
+                } else {
+                    throw e;
+                }
+            }
         }
-        server.terminate();
+
+        try {
+            AuthCacheValue.setAuthCache(cache);
+            client("http://localhost:" + server.getLocalPort() + "/d1/foo.html");
+        } finally {
+            if (server != null) {
+                server.terminate();
+            }
+        }
+
+        f = auth.getCount();
+        if (f != 1) {
+            except("Authenticator was called " + f + " times. Should be 1");
+        }
     }
 
     public static void except (String s) {
@@ -163,7 +196,7 @@
             super ();
         }
 
-        int count = 0;
+        volatile int count = 0;
 
         public PasswordAuthentication getPasswordAuthentication () {
             PasswordAuthentication pw;
@@ -178,7 +211,7 @@
     }
 
     static class CacheImpl extends AuthCacheImpl {
-        HashMap map;
+        HashMap<String,LinkedList<AuthCacheValue>> map;
         int port; // need to store the port number the server is using
 
         CacheImpl () throws IOException {
@@ -190,20 +223,18 @@
             this.port = port;
             File src = new File ("cache.ser");
             if (src.exists()) {
-                ObjectInputStream is = new ObjectInputStream (
-                    new FileInputStream (src)
-                );
-                try {
-                    map = (HashMap)is.readObject ();
+                try (ObjectInputStream is = new ObjectInputStream(
+                        new FileInputStream(src))) {
+                    map = (HashMap<String,LinkedList<AuthCacheValue>>)is
+                              .readObject();
                     this.port = (Integer)is.readObject ();
                     System.out.println ("read port from file " + port);
                 } catch (ClassNotFoundException e) {
                     assert false;
                 }
-                is.close();
                 System.out.println ("setMap from cache.ser");
             } else {
-                map = new HashMap();
+                map = new HashMap<>();
             }
             setMap (map);
         }
@@ -213,20 +244,22 @@
         }
 
         private void writeMap () {
+            File dst = new File("cache.ser");
             try {
-                File dst = new File ("cache.ser");
                 dst.delete();
                 if (!dst.createNewFile()) {
                     return;
                 }
-                ObjectOutputStream os = new ObjectOutputStream (
-                        new FileOutputStream (dst)
-                );
+            } catch (IOException e) {
+            }
+
+            try (ObjectOutputStream os = new ObjectOutputStream(
+                    new FileOutputStream(dst))) {
                 os.writeObject(map);
                 os.writeObject(port);
-                System.out.println ("wrote port " + port);
-                os.close();
-            } catch (IOException e) {}
+                System.out.println("wrote port " + port);
+            } catch (IOException e) {
+            }
         }
 
         public void put (String pkey, AuthCacheValue value) {
diff --git a/jdk/test/java/net/Authenticator/B4933582.sh b/jdk/test/java/net/Authenticator/B4933582.sh
deleted file mode 100644
index e1cca02..0000000
--- a/jdk/test/java/net/Authenticator/B4933582.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please 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 4933582
-
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin | AIX )
-    PS=":"
-    FS="/"
-    ;;
-  CYGWIN* )
-    PS=";"
-    FS="/"
-    ;;
-  Windows* )
-    PS=";"
-    FS="\\"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-EXTRAOPTS="--add-exports java.base/sun.net.www=ALL-UNNAMED --add-exports java.base/sun.net.www.protocol.http=ALL-UNNAMED"
-export EXTRAOPTS
-
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . \
-    -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest" ${TESTSRC}${FS}B4933582.java
-rm -f cache.ser auth.save
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 first
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 second
diff --git a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java
new file mode 100644
index 0000000..543ebc5
--- /dev/null
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java
@@ -0,0 +1,295 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.HttpURLConnection;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @test
+ * @bug 8169415
+ * @library /lib/testlibrary/
+ * @modules java.base/sun.net.www
+ *          java.base/sun.net.www.protocol.http
+ *          jdk.httpserver/sun.net.httpserver
+ * @build jdk.testlibrary.SimpleSSLContext HTTPTest HTTPTestServer HTTPTestClient HTTPSetAuthenticatorTest
+ * @summary A simple HTTP test that starts an echo server supporting the given
+ *          authentication scheme, then starts a regular HTTP client to invoke it.
+ *          The client first does a GET request on "/", then follows on
+ *          with a POST request that sends "Hello World!" to the server.
+ *          The client expects to receive "Hello World!" in return.
+ *          The test supports several execution modes:
+ *            SERVER: The server performs Server authentication;
+ *            PROXY:  The server pretends to be a proxy and performs
+ *                    Proxy authentication;
+ *            SERVER307: The server redirects the client (307) to another
+ *                    server that perform Server authentication;
+ *            PROXY305: The server attempts to redirect
+ *                    the client to a proxy using 305 code;
+ *           This test runs the client several times, providing different
+ *           authenticators to the HttpURLConnection and verifies that
+ *           the authenticator is invoked as expected - validating that
+ *           connections with different authenticators do not share each
+ *           other's socket channel and authentication info.
+ *           Note: BASICSERVER means that the server will let the underlying
+ *                 com.sun.net.httpserver.HttpServer perform BASIC
+ *                 authentication when in Server mode. There should be
+ *                 no real difference between BASICSERVER and BASIC - it should
+ *                 be transparent on the client side.
+ * @run main/othervm HTTPSetAuthenticatorTest NONE SERVER PROXY SERVER307 PROXY305
+ * @run main/othervm HTTPSetAuthenticatorTest DIGEST SERVER
+ * @run main/othervm HTTPSetAuthenticatorTest DIGEST PROXY
+ * @run main/othervm HTTPSetAuthenticatorTest DIGEST PROXY305
+ * @run main/othervm HTTPSetAuthenticatorTest DIGEST SERVER307
+ * @run main/othervm HTTPSetAuthenticatorTest BASIC  SERVER
+ * @run main/othervm HTTPSetAuthenticatorTest BASIC  PROXY
+ * @run main/othervm HTTPSetAuthenticatorTest BASIC  PROXY305
+ * @run main/othervm HTTPSetAuthenticatorTest BASIC  SERVER307
+ * @run main/othervm HTTPSetAuthenticatorTest BASICSERVER SERVER
+ * @run main/othervm HTTPSetAuthenticatorTest BASICSERVER SERVER307
+ *
+ * @author danielfuchs
+ */
+public class HTTPSetAuthenticatorTest extends HTTPTest {
+
+    public static void main(String[] args) throws Exception {
+        String[] schemes;
+        String[] params;
+         if (args == null || args.length == 0) {
+            schemes = Stream.of(HttpSchemeType.values())
+                        .map(HttpSchemeType::name)
+                        .collect(Collectors.toList())
+                        .toArray(new String[0]);
+            params = new String[0];
+        } else {
+            schemes = new String[] { args[0] };
+            params = Arrays.copyOfRange(args, 1, args.length);
+        }
+        for (String scheme : schemes) {
+            System.out.println("==== Testing with scheme=" + scheme + " ====\n");
+            new HTTPSetAuthenticatorTest(HttpSchemeType.valueOf(scheme))
+                .execute(params);
+            System.out.println();
+        }
+    }
+
+    final HttpSchemeType scheme;
+    public HTTPSetAuthenticatorTest(HttpSchemeType scheme) {
+        this.scheme = scheme;
+    }
+
+    @Override
+    public HttpSchemeType getHttpSchemeType() {
+        return scheme;
+    }
+
+    @Override
+    public int run(HTTPTestServer server,
+                   HttpProtocolType protocol,
+                   HttpAuthType mode)
+            throws IOException
+    {
+        HttpTestAuthenticator authOne = new HttpTestAuthenticator("dublin", "foox");
+        HttpTestAuthenticator authTwo = new HttpTestAuthenticator("dublin", "foox");
+        int expectedIncrement = scheme == HttpSchemeType.NONE
+                                ? 0 : EXPECTED_AUTH_CALLS_PER_TEST;
+        int count;
+        int defaultCount = AUTHENTICATOR.count.get();
+
+        // Connect to the server with a GET request, then with a
+        // POST that contains "Hello World!"
+        // Uses authenticator #1
+        System.out.println("\nClient: Using authenticator #1: "
+            + toString(authOne));
+        HTTPTestClient.connect(protocol, server, mode, authOne);
+        count = authOne.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #1 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+
+        // Connect to the server with a GET request, then with a
+        // POST that contains "Hello World!"
+        // Uses authenticator #2
+        System.out.println("\nClient: Using authenticator #2: "
+            + toString(authTwo));
+        HTTPTestClient.connect(protocol, server, mode, authTwo);
+        count = authTwo.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #2 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+        count = authTwo.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #2 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+
+        // Connect to the server with a GET request, then with a
+        // POST that contains "Hello World!"
+        // Uses authenticator #1
+        System.out.println("\nClient: Using authenticator #1 again: "
+            + toString(authOne));
+        HTTPTestClient.connect(protocol, server, mode, authOne);
+        count = authOne.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #1 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+        count = authTwo.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #2 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+        count =  AUTHENTICATOR.count.get();
+        if (count != defaultCount) {
+            throw new AssertionError("Default Authenticator called " + count(count)
+                + " expected it to be called " + expected(defaultCount));
+        }
+
+        // Now tries with the default authenticator: it should be invoked.
+        System.out.println("\nClient: Using the default authenticator: "
+            + toString(null));
+        HTTPTestClient.connect(protocol, server, mode, null);
+        count = authOne.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #1 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+        count = authTwo.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #2 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+        count =  AUTHENTICATOR.count.get();
+        if (count != defaultCount + expectedIncrement) {
+            throw new AssertionError("Default Authenticator called " + count(count)
+                + " expected it to be called " + expected(defaultCount + expectedIncrement));
+        }
+
+        // Now tries with explicitly setting the default authenticator: it should
+        // be invoked again.
+        // Uncomment the code below when 8169068 is available.
+//        System.out.println("\nClient: Explicitly setting the default authenticator: "
+//            + toString(Authenticator.getDefault()));
+//        HTTPTestClient.connect(protocol, server, mode, Authenticator.getDefault());
+//        count = authOne.count.get();
+//        if (count != expectedIncrement) {
+//            throw new AssertionError("Authenticator #1 called " + count(count)
+//                + " expected it to be called " + expected(expectedIncrement));
+//        }
+//        count = authTwo.count.get();
+//        if (count != expectedIncrement) {
+//            throw new AssertionError("Authenticator #2 called " + count(count)
+//                + " expected it to be called " + expected(expectedIncrement));
+//        }
+//        count =  AUTHENTICATOR.count.get();
+//        if (count != defaultCount + 2 * expectedIncrement) {
+//            throw new AssertionError("Default Authenticator called " + count(count)
+//                + " expected it to be called "
+//                + expected(defaultCount + 2 * expectedIncrement));
+//        }
+
+        // Now tries to set an authenticator on a connected connection.
+        URL url = url(protocol,  server.getAddress(), "/");
+        Proxy proxy = proxy(server, mode);
+        HttpURLConnection conn = openConnection(url, mode, proxy);
+        try {
+            conn.setAuthenticator(null);
+            throw new RuntimeException("Expected NullPointerException"
+                    + " trying to set a null authenticator"
+                    + " not raised.");
+        } catch (NullPointerException npe) {
+            System.out.println("Client: caught expected NPE"
+                    + " trying to set a null authenticator: "
+                    + npe);
+        }
+        conn.connect();
+        try {
+            try {
+                conn.setAuthenticator(authOne);
+                throw new RuntimeException("Expected IllegalStateException"
+                        + " trying to set an authenticator after connect"
+                        + " not raised.");
+            } catch (IllegalStateException ise) {
+                System.out.println("Client: caught expected ISE"
+                        + " trying to set an authenticator after connect: "
+                        + ise);
+            }
+            // Uncomment the code below when 8169068 is available.
+//            try {
+//                conn.setAuthenticator(Authenticator.getDefault());
+//                throw new RuntimeException("Expected IllegalStateException"
+//                        + " trying to set an authenticator after connect"
+//                        + " not raised.");
+//            } catch (IllegalStateException ise) {
+//                System.out.println("Client: caught expected ISE"
+//                        + " trying to set an authenticator after connect: "
+//                        + ise);
+//            }
+            try {
+                conn.setAuthenticator(null);
+                throw new RuntimeException("Expected"
+                        + " IllegalStateException or NullPointerException"
+                        + " trying to set a null authenticator after connect"
+                        + " not raised.");
+            } catch (IllegalStateException | NullPointerException xxe) {
+                System.out.println("Client: caught expected "
+                        + xxe.getClass().getSimpleName()
+                        + " trying to set a null authenticator after connect: "
+                        + xxe);
+            }
+        } finally {
+            conn.disconnect();
+        }
+
+        // double check that authOne and authTwo haven't been invoked.
+        count = authOne.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #1 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+        count = authTwo.count.get();
+        if (count != expectedIncrement) {
+            throw new AssertionError("Authenticator #2 called " + count(count)
+                + " expected it to be called " + expected(expectedIncrement));
+        }
+
+        // All good!
+        // return the number of times the default authenticator is supposed
+        // to have been called.
+        return scheme == HttpSchemeType.NONE ? 0 : 1 * EXPECTED_AUTH_CALLS_PER_TEST;
+    }
+
+    static String toString(Authenticator a) {
+        return sun.net.www.protocol.http.AuthenticatorKeys.getKey(a);
+    }
+
+}
diff --git a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java
new file mode 100644
index 0000000..87e9a4b
--- /dev/null
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.Authenticator;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.PasswordAuthentication;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Stream;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import jdk.testlibrary.SimpleSSLContext;
+
+/**
+ * @test
+ * @bug 8169415
+ * @library /lib/testlibrary/
+ * @modules java.base/sun.net.www
+ *          jdk.httpserver/sun.net.httpserver
+ * @build jdk.testlibrary.SimpleSSLContext HTTPTest HTTPTestServer HTTPTestClient
+ * @summary A simple HTTP test that starts an echo server supporting Digest
+ *          authentication, then starts a regular HTTP client to invoke it.
+ *          The client first does a GET request on "/", then follows on
+ *          with a POST request that sends "Hello World!" to the server.
+ *          The client expects to receive "Hello World!" in return.
+ *          The test supports several execution modes:
+ *            SERVER: The server performs Digest Server authentication;
+ *            PROXY:  The server pretends to be a proxy and performs
+ *                    Digest Proxy authentication;
+ *            SERVER307: The server redirects the client (307) to another
+ *                    server that perform Digest authentication;
+ *            PROXY305: The server attempts to redirect
+ *                    the client to a proxy using 305 code;
+ * @run main/othervm HTTPTest SERVER
+ * @run main/othervm HTTPTest PROXY
+ * @run main/othervm HTTPTest SERVER307
+ * @run main/othervm HTTPTest PROXY305
+ *
+ * @author danielfuchs
+ */
+public class HTTPTest {
+
+    public static final boolean DEBUG =
+         Boolean.parseBoolean(System.getProperty("test.debug", "false"));
+    public static enum HttpAuthType { SERVER, PROXY, SERVER307, PROXY305 };
+    public static enum HttpProtocolType { HTTP, HTTPS };
+    public static enum HttpSchemeType { NONE, BASICSERVER, BASIC, DIGEST };
+    public static final HttpAuthType DEFAULT_HTTP_AUTH_TYPE = HttpAuthType.SERVER;
+    public static final HttpProtocolType DEFAULT_PROTOCOL_TYPE = HttpProtocolType.HTTP;
+    public static final HttpSchemeType DEFAULT_SCHEME_TYPE = HttpSchemeType.DIGEST;
+
+    public static class HttpTestAuthenticator extends Authenticator {
+        private final String realm;
+        private final String username;
+        // Used to prevent incrementation of 'count' when calling the
+        // authenticator from the server side.
+        private final ThreadLocal<Boolean> skipCount = new ThreadLocal<>();
+        // count will be incremented every time getPasswordAuthentication()
+        // is called from the client side.
+        final AtomicInteger count = new AtomicInteger();
+
+        public HttpTestAuthenticator(String realm, String username) {
+            this.realm = realm;
+            this.username = username;
+        }
+
+        @Override
+        protected PasswordAuthentication getPasswordAuthentication() {
+            if (skipCount.get() == null || skipCount.get().booleanValue() == false) {
+                System.out.println("Authenticator called: " + count.incrementAndGet());
+            }
+            return new PasswordAuthentication(getUserName(),
+                    new char[] {'b','a','r'});
+        }
+
+        // Called by the server side to get the password of the user
+        // being authentified.
+        public final char[] getPassword(String user) {
+            if (user.equals(username)) {
+                skipCount.set(Boolean.TRUE);
+                try {
+                    return getPasswordAuthentication().getPassword();
+                } finally {
+                    skipCount.set(Boolean.FALSE);
+                }
+            }
+            throw new SecurityException("User unknown: " + user);
+        }
+
+        public final String getUserName() {
+            return username;
+        }
+        public final String getRealm() {
+            return realm;
+        }
+
+    }
+    public static final HttpTestAuthenticator AUTHENTICATOR;
+    static {
+        AUTHENTICATOR = new HttpTestAuthenticator("dublin", "foox");
+        Authenticator.setDefault(AUTHENTICATOR);
+    }
+
+    static {
+        try {
+            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+                public boolean verify(String hostname, SSLSession session) {
+                    return true;
+                }
+            });
+            SSLContext.setDefault(new SimpleSSLContext().get());
+        } catch (IOException ex) {
+            throw new ExceptionInInitializerError(ex);
+        }
+    }
+
+    static final Logger logger = Logger.getLogger ("com.sun.net.httpserver");
+    static {
+        if (DEBUG) logger.setLevel(Level.ALL);
+        Stream.of(Logger.getLogger("").getHandlers())
+              .forEach(h -> h.setLevel(Level.ALL));
+    }
+
+    static final int EXPECTED_AUTH_CALLS_PER_TEST = 1;
+
+    public static void main(String[] args) throws Exception {
+        // new HTTPTest().execute(HttpAuthType.SERVER.name());
+        new HTTPTest().execute(args);
+    }
+
+    public void execute(String... args) throws Exception {
+        Stream<HttpAuthType> modes;
+        if (args == null || args.length == 0) {
+            modes = Stream.of(HttpAuthType.values());
+        } else {
+            modes = Stream.of(args).map(HttpAuthType::valueOf);
+        }
+        modes.forEach(this::test);
+        System.out.println("Test PASSED - Authenticator called: "
+                 + expected(AUTHENTICATOR.count.get()));
+    }
+
+    public void test(HttpAuthType mode) {
+        for (HttpProtocolType type: HttpProtocolType.values()) {
+            test(type, mode);
+        }
+    }
+
+    public HttpSchemeType getHttpSchemeType() {
+        return DEFAULT_SCHEME_TYPE;
+    }
+
+    public void test(HttpProtocolType protocol, HttpAuthType mode) {
+        if (mode == HttpAuthType.PROXY305 && protocol == HttpProtocolType.HTTPS ) {
+            // silently skip unsupported test combination
+            return;
+        }
+        System.out.println("\n**** Testing " + protocol + " "
+                           + mode + " mode ****\n");
+        int authCount = AUTHENTICATOR.count.get();
+        int expectedIncrement = 0;
+        try {
+            // Creates an HTTP server that echoes back whatever is in the
+            // request body.
+            HTTPTestServer server =
+                    HTTPTestServer.create(protocol,
+                                          mode,
+                                          AUTHENTICATOR,
+                                          getHttpSchemeType());
+            try {
+                expectedIncrement += run(server, protocol, mode);
+            } finally {
+                server.stop();
+            }
+        }  catch (IOException ex) {
+            ex.printStackTrace(System.err);
+            throw new UncheckedIOException(ex);
+        }
+        int count = AUTHENTICATOR.count.get();
+        if (count != authCount + expectedIncrement) {
+            throw new AssertionError("Authenticator called " + count(count)
+                        + " expected it to be called "
+                        + expected(authCount + expectedIncrement));
+        }
+    }
+
+    /**
+     * Runs the test with the given parameters.
+     * @param server    The server
+     * @param protocol  The protocol (HTTP/HTTPS)
+     * @param mode      The mode (PROXY, SERVER, SERVER307...)
+     * @return The number of times the default authenticator should have been
+     *         called.
+     * @throws IOException in case of connection or protocol issues
+     */
+    public int run(HTTPTestServer server,
+                   HttpProtocolType protocol,
+                   HttpAuthType mode)
+            throws IOException
+    {
+        // Connect to the server with a GET request, then with a
+        // POST that contains "Hello World!"
+        HTTPTestClient.connect(protocol, server, mode, null);
+        // return the number of times the default authenticator is supposed
+        // to have been called.
+        return EXPECTED_AUTH_CALLS_PER_TEST;
+    }
+
+    public static String count(int count) {
+        switch(count) {
+            case 0: return "not even once";
+            case 1: return "once";
+            case 2: return "twice";
+            default: return String.valueOf(count) + " times";
+        }
+    }
+
+    public static String expected(int count) {
+        switch(count) {
+            default: return count(count);
+        }
+    }
+    public static String protocol(HttpProtocolType type) {
+        return type.name().toLowerCase(Locale.US);
+    }
+
+    public static URL url(HttpProtocolType protocol, InetSocketAddress address,
+                          String path) throws MalformedURLException {
+        return new URL(protocol(protocol),
+                       address.getHostString(),
+                       address.getPort(), path);
+    }
+
+    public static Proxy proxy(HTTPTestServer server, HttpAuthType authType) {
+        return (authType == HttpAuthType.PROXY)
+               ? new Proxy(Proxy.Type.HTTP, server.getAddress())
+               : null;
+    }
+
+    public static HttpURLConnection openConnection(URL url,
+                                                   HttpAuthType authType,
+                                                   Proxy proxy)
+                                    throws IOException {
+
+        HttpURLConnection conn = (HttpURLConnection)
+                (authType == HttpAuthType.PROXY
+                    ? url.openConnection(proxy)
+                    : url.openConnection());
+        return conn;
+    }
+}
diff --git a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java
new file mode 100644
index 0000000..3da0a7a
--- /dev/null
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import javax.net.ssl.HttpsURLConnection;
+
+/**
+ * A simple Http client that connects to the HTTPTestServer.
+ * @author danielfuchs
+ */
+public class HTTPTestClient extends HTTPTest {
+
+    public static void connect(HttpProtocolType protocol,
+                               HTTPTestServer server,
+                               HttpAuthType authType,
+                               Authenticator auth)
+            throws IOException {
+
+        InetSocketAddress address = server.getAddress();
+        final URL url = url(protocol,  address, "/");
+        final Proxy proxy = proxy(server, authType);
+
+        System.out.println("Client: FIRST request: " + url + " GET");
+        HttpURLConnection conn = openConnection(url, authType, proxy);
+        configure(conn, auth);
+        System.out.println("Response code: " + conn.getResponseCode());
+        String result = new String(conn.getInputStream().readAllBytes(), "UTF-8");
+        System.out.println("Response body: " + result);
+        if (!result.isEmpty()) {
+            throw new RuntimeException("Unexpected response to GET: " + result);
+        }
+        System.out.println("\nClient: NEXT request: " + url + " POST");
+        conn = openConnection(url, authType, proxy);
+        configure(conn, auth);
+        conn.setRequestMethod("POST");
+        conn.setDoOutput(true);
+        conn.setDoInput(true);
+        conn.getOutputStream().write("Hello World!".getBytes("UTF-8"));
+        System.out.println("Response code: " + conn.getResponseCode());
+        result = new String(conn.getInputStream().readAllBytes(), "UTF-8");
+        System.out.println("Response body: " + result);
+        if ("Hello World!".equals(result)) {
+            System.out.println("Test passed!");
+        } else {
+            throw new RuntimeException("Unexpected response to POST: " + result);
+        }
+    }
+
+    private static void configure(HttpURLConnection conn, Authenticator auth)
+        throws IOException {
+        if (auth != null) {
+            conn.setAuthenticator(auth);
+        }
+        if (conn instanceof HttpsURLConnection) {
+            System.out.println("Client: configuring SSL connection");
+            // We have set a default SSLContext so we don't need to do
+            // anything here. Otherwise it could look like:
+            //     HttpsURLConnection httpsConn = (HttpsURLConnection)conn;
+            //     httpsConn.setSSLSocketFactory(
+            //               new SimpleSSLContext().get().getSocketFactory());
+        }
+    }
+
+}
diff --git a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java
new file mode 100644
index 0000000..6479de1
--- /dev/null
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java
@@ -0,0 +1,995 @@
+/*
+ * 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.
+ */
+
+import com.sun.net.httpserver.BasicAuthenticator;
+import com.sun.net.httpserver.Filter;
+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 com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsParameters;
+import com.sun.net.httpserver.HttpsServer;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.math.BigInteger;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.List;
+import java.util.Objects;
+import java.util.Random;
+import java.util.stream.Collectors;
+import javax.net.ssl.SSLContext;
+import sun.net.www.HeaderParser;
+
+/**
+ * A simple HTTP server that supports Digest authentication.
+ * By default this server will echo back whatever is present
+ * in the request body.
+ * @author danielfuchs
+ */
+public class HTTPTestServer extends HTTPTest {
+
+    final HttpServer      serverImpl; // this server endpoint
+    final HTTPTestServer  redirect;   // the target server where to redirect 3xx
+    final HttpHandler     delegate;   // unused
+
+    private HTTPTestServer(HttpServer server, HTTPTestServer target,
+                           HttpHandler delegate) {
+        this.serverImpl = server;
+        this.redirect = target;
+        this.delegate = delegate;
+    }
+
+    public static void main(String[] args)
+            throws IOException {
+
+           HTTPTestServer server = create(HTTPTest.DEFAULT_PROTOCOL_TYPE,
+                                          HTTPTest.DEFAULT_HTTP_AUTH_TYPE,
+                                          HTTPTest.AUTHENTICATOR,
+                                          HTTPTest.DEFAULT_SCHEME_TYPE);
+           try {
+               System.out.println("Server created at " + server.getAddress());
+               System.out.println("Strike <Return> to exit");
+               System.in.read();
+           } finally {
+               System.out.println("stopping server");
+               server.stop();
+           }
+    }
+
+    private static String toString(Headers headers) {
+        return headers.entrySet().stream()
+                .map((e) -> e.getKey() + ": " + e.getValue())
+                .collect(Collectors.joining("\n"));
+    }
+
+    public static HTTPTestServer create(HttpProtocolType protocol,
+                                        HttpAuthType authType,
+                                        HttpTestAuthenticator auth,
+                                        HttpSchemeType schemeType)
+            throws IOException {
+        return create(protocol, authType, auth, schemeType, null);
+    }
+
+    public static HTTPTestServer create(HttpProtocolType protocol,
+                                        HttpAuthType authType,
+                                        HttpTestAuthenticator auth,
+                                        HttpSchemeType schemeType,
+                                        HttpHandler delegate)
+            throws IOException {
+        Objects.requireNonNull(authType);
+        Objects.requireNonNull(auth);
+        switch(authType) {
+            // A server that performs Server Digest authentication.
+            case SERVER: return createServer(protocol, authType, auth,
+                                             schemeType, delegate, "/");
+            // A server that pretends to be a Proxy and performs
+            // Proxy Digest authentication. If protocol is HTTPS,
+            // then this will create a HttpsProxyTunnel that will
+            // handle the CONNECT request for tunneling.
+            case PROXY: return createProxy(protocol, authType, auth,
+                                           schemeType, delegate, "/");
+            // A server that sends 307 redirect to a server that performs
+            // Digest authentication.
+            // Note: 301 doesn't work here because it transforms POST into GET.
+            case SERVER307: return createServerAndRedirect(protocol,
+                                                        HttpAuthType.SERVER,
+                                                        auth, schemeType,
+                                                        delegate, 307);
+            // A server that sends 305 redirect to a proxy that performs
+            // Digest authentication.
+            case PROXY305:  return createServerAndRedirect(protocol,
+                                                        HttpAuthType.PROXY,
+                                                        auth, schemeType,
+                                                        delegate, 305);
+            default:
+                throw new InternalError("Unknown server type: " + authType);
+        }
+    }
+
+    static HttpServer createHttpServer(HttpProtocolType protocol) throws IOException {
+        switch (protocol) {
+            case HTTP:  return HttpServer.create();
+            case HTTPS: return configure(HttpsServer.create());
+            default: throw new InternalError("Unsupported protocol " + protocol);
+        }
+    }
+
+    static HttpsServer configure(HttpsServer server) throws IOException {
+        try {
+            SSLContext ctx = SSLContext.getDefault();
+            server.setHttpsConfigurator(new Configurator(ctx));
+        } catch (NoSuchAlgorithmException ex) {
+            throw new IOException(ex);
+        }
+        return server;
+    }
+
+
+    static void setContextAuthenticator(HttpContext ctxt,
+                                        HttpTestAuthenticator auth) {
+        final String realm = auth.getRealm();
+        com.sun.net.httpserver.Authenticator authenticator =
+            new BasicAuthenticator(realm) {
+                @Override
+                public boolean checkCredentials(String username, String pwd) {
+                    return auth.getUserName().equals(username)
+                           && new String(auth.getPassword(username)).equals(pwd);
+                }
+        };
+        ctxt.setAuthenticator(authenticator);
+    }
+
+    public static HTTPTestServer createServer(HttpProtocolType protocol,
+                                        HttpAuthType authType,
+                                        HttpTestAuthenticator auth,
+                                        HttpSchemeType schemeType,
+                                        HttpHandler delegate,
+                                        String path)
+            throws IOException {
+        Objects.requireNonNull(authType);
+        Objects.requireNonNull(auth);
+
+        HttpServer impl = createHttpServer(protocol);
+        final HTTPTestServer server = new HTTPTestServer(impl, null, delegate);
+        final HttpHandler hh = server.createHandler(schemeType, auth, authType);
+        HttpContext ctxt = impl.createContext(path, hh);
+        server.configureAuthentication(ctxt, schemeType, auth, authType);
+        impl.bind(new InetSocketAddress("127.0.0.1", 0), 0);
+        impl.start();
+        return server;
+    }
+
+    public static HTTPTestServer createProxy(HttpProtocolType protocol,
+                                        HttpAuthType authType,
+                                        HttpTestAuthenticator auth,
+                                        HttpSchemeType schemeType,
+                                        HttpHandler delegate,
+                                        String path)
+            throws IOException {
+        Objects.requireNonNull(authType);
+        Objects.requireNonNull(auth);
+
+        HttpServer impl = createHttpServer(protocol);
+        final HTTPTestServer server = protocol == HttpProtocolType.HTTPS
+                ? new HttpsProxyTunnel(impl, null, delegate)
+                : new HTTPTestServer(impl, null, delegate);
+        final HttpHandler hh = server.createHandler(schemeType, auth, authType);
+        HttpContext ctxt = impl.createContext(path, hh);
+        server.configureAuthentication(ctxt, schemeType, auth, authType);
+
+        impl.bind(new InetSocketAddress("127.0.0.1", 0), 0);
+        impl.start();
+
+        return server;
+    }
+
+    public static HTTPTestServer createServerAndRedirect(
+                                        HttpProtocolType protocol,
+                                        HttpAuthType targetAuthType,
+                                        HttpTestAuthenticator auth,
+                                        HttpSchemeType schemeType,
+                                        HttpHandler targetDelegate,
+                                        int code300)
+            throws IOException {
+        Objects.requireNonNull(targetAuthType);
+        Objects.requireNonNull(auth);
+
+        // The connection between client and proxy can only
+        // be a plain connection: SSL connection to proxy
+        // is not supported by our client connection.
+        HttpProtocolType targetProtocol = targetAuthType == HttpAuthType.PROXY
+                                          ? HttpProtocolType.HTTP
+                                          : protocol;
+        HTTPTestServer redirectTarget =
+                (targetAuthType == HttpAuthType.PROXY)
+                ? createProxy(protocol, targetAuthType,
+                              auth, schemeType, targetDelegate, "/")
+                : createServer(targetProtocol, targetAuthType,
+                               auth, schemeType, targetDelegate, "/");
+        HttpServer impl = createHttpServer(protocol);
+        final HTTPTestServer redirectingServer =
+                 new HTTPTestServer(impl, redirectTarget, null);
+        InetSocketAddress redirectAddr = redirectTarget.getAddress();
+        URL locationURL = url(targetProtocol, redirectAddr, "/");
+        final HttpHandler hh = redirectingServer.create300Handler(locationURL,
+                                             HttpAuthType.SERVER, code300);
+        impl.createContext("/", hh);
+        impl.bind(new InetSocketAddress("127.0.0.1", 0), 0);
+        impl.start();
+        return redirectingServer;
+    }
+
+    public InetSocketAddress getAddress() {
+        return serverImpl.getAddress();
+    }
+
+    public void stop() {
+        serverImpl.stop(0);
+        if (redirect != null) {
+            redirect.stop();
+        }
+    }
+
+    protected void writeResponse(HttpExchange he) throws IOException {
+        if (delegate == null) {
+            he.sendResponseHeaders(HttpURLConnection.HTTP_OK, 0);
+            he.getResponseBody().write(he.getRequestBody().readAllBytes());
+        } else {
+            delegate.handle(he);
+        }
+    }
+
+    private HttpHandler createHandler(HttpSchemeType schemeType,
+                                      HttpTestAuthenticator auth,
+                                      HttpAuthType authType) {
+        return new HttpNoAuthHandler(authType);
+    }
+
+    private void configureAuthentication(HttpContext ctxt,
+                            HttpSchemeType schemeType,
+                            HttpTestAuthenticator auth,
+                            HttpAuthType authType) {
+        switch(schemeType) {
+            case DIGEST:
+                // DIGEST authentication is handled by the handler.
+                ctxt.getFilters().add(new HttpDigestFilter(auth, authType));
+                break;
+            case BASIC:
+                // BASIC authentication is handled by the filter.
+                ctxt.getFilters().add(new HttpBasicFilter(auth, authType));
+                break;
+            case BASICSERVER:
+                switch(authType) {
+                    case PROXY: case PROXY305:
+                        // HttpServer can't support Proxy-type authentication
+                        // => we do as if BASIC had been specified, and we will
+                        //    handle authentication in the handler.
+                        ctxt.getFilters().add(new HttpBasicFilter(auth, authType));
+                        break;
+                    case SERVER: case SERVER307:
+                        // Basic authentication is handled by HttpServer
+                        // directly => the filter should not perform
+                        // authentication again.
+                        setContextAuthenticator(ctxt, auth);
+                        ctxt.getFilters().add(new HttpNoAuthFilter(authType));
+                        break;
+                    default:
+                        throw new InternalError("Invalid combination scheme="
+                             + schemeType + " authType=" + authType);
+                }
+            case NONE:
+                // No authentication at all.
+                ctxt.getFilters().add(new HttpNoAuthFilter(authType));
+                break;
+            default:
+                throw new InternalError("No such scheme: " + schemeType);
+        }
+    }
+
+    private HttpHandler create300Handler(URL proxyURL,
+        HttpAuthType type, int code300) throws MalformedURLException {
+        return new Http3xxHandler(proxyURL, type, code300);
+    }
+
+    // Abstract HTTP filter class.
+    private abstract static class AbstractHttpFilter extends Filter {
+
+        final HttpAuthType authType;
+        final String type;
+        public AbstractHttpFilter(HttpAuthType authType, String type) {
+            this.authType = authType;
+            this.type = type;
+        }
+
+        String getLocation() {
+            return "Location";
+        }
+        String getAuthenticate() {
+            return authType == HttpAuthType.PROXY
+                    ? "Proxy-Authenticate" : "WWW-Authenticate";
+        }
+        String getAuthorization() {
+            return authType == HttpAuthType.PROXY
+                    ? "Proxy-Authorization" : "Authorization";
+        }
+        int getUnauthorizedCode() {
+            return authType == HttpAuthType.PROXY
+                    ? HttpURLConnection.HTTP_PROXY_AUTH
+                    : HttpURLConnection.HTTP_UNAUTHORIZED;
+        }
+        String getKeepAlive() {
+            return "keep-alive";
+        }
+        String getConnection() {
+            return authType == HttpAuthType.PROXY
+                    ? "Proxy-Connection" : "Connection";
+        }
+        protected abstract boolean isAuthentified(HttpExchange he) throws IOException;
+        protected abstract void requestAuthentication(HttpExchange he) throws IOException;
+        protected void accept(HttpExchange he, Chain chain) throws IOException {
+            chain.doFilter(he);
+        }
+
+        @Override
+        public String description() {
+            return "Filter for " + type;
+        }
+        @Override
+        public void doFilter(HttpExchange he, Chain chain) throws IOException {
+            try {
+                System.out.println(type + ": Got " + he.getRequestMethod()
+                    + ": " + he.getRequestURI()
+                    + "\n" + HTTPTestServer.toString(he.getRequestHeaders()));
+                if (!isAuthentified(he)) {
+                    try {
+                        requestAuthentication(he);
+                        he.sendResponseHeaders(getUnauthorizedCode(), 0);
+                        System.out.println(type
+                            + ": Sent back " + getUnauthorizedCode());
+                    } finally {
+                        he.close();
+                    }
+                } else {
+                    accept(he, chain);
+                }
+            } catch (RuntimeException | Error | IOException t) {
+               System.err.println(type
+                    + ": Unexpected exception while handling request: " + t);
+               t.printStackTrace(System.err);
+               he.close();
+               throw t;
+            }
+        }
+
+    }
+
+    private final static class DigestResponse {
+        final String realm;
+        final String username;
+        final String nonce;
+        final String cnonce;
+        final String nc;
+        final String uri;
+        final String algorithm;
+        final String response;
+        final String qop;
+        final String opaque;
+
+        public DigestResponse(String realm, String username, String nonce,
+                              String cnonce, String nc, String uri,
+                              String algorithm, String qop, String opaque,
+                              String response) {
+            this.realm = realm;
+            this.username = username;
+            this.nonce = nonce;
+            this.cnonce = cnonce;
+            this.nc = nc;
+            this.uri = uri;
+            this.algorithm = algorithm;
+            this.qop = qop;
+            this.opaque = opaque;
+            this.response = response;
+        }
+
+        String getAlgorithm(String defval) {
+            return algorithm == null ? defval : algorithm;
+        }
+        String getQoP(String defval) {
+            return qop == null ? defval : qop;
+        }
+
+        // Code stolen from DigestAuthentication:
+
+        private static final char charArray[] = {
+            '0', '1', '2', '3', '4', '5', '6', '7',
+            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+        };
+
+        private static String encode(String src, char[] passwd, MessageDigest md) {
+            try {
+                md.update(src.getBytes("ISO-8859-1"));
+            } catch (java.io.UnsupportedEncodingException uee) {
+                assert false;
+            }
+            if (passwd != null) {
+                byte[] passwdBytes = new byte[passwd.length];
+                for (int i=0; i<passwd.length; i++)
+                    passwdBytes[i] = (byte)passwd[i];
+                md.update(passwdBytes);
+                Arrays.fill(passwdBytes, (byte)0x00);
+            }
+            byte[] digest = md.digest();
+
+            StringBuilder res = new StringBuilder(digest.length * 2);
+            for (int i = 0; i < digest.length; i++) {
+                int hashchar = ((digest[i] >>> 4) & 0xf);
+                res.append(charArray[hashchar]);
+                hashchar = (digest[i] & 0xf);
+                res.append(charArray[hashchar]);
+            }
+            return res.toString();
+        }
+
+        public static String computeDigest(boolean isRequest,
+                                            String reqMethod,
+                                            char[] password,
+                                            DigestResponse params)
+            throws NoSuchAlgorithmException
+        {
+
+            String A1, HashA1;
+            String algorithm = params.getAlgorithm("MD5");
+            boolean md5sess = algorithm.equalsIgnoreCase ("MD5-sess");
+
+            MessageDigest md = MessageDigest.getInstance(md5sess?"MD5":algorithm);
+
+            if (params.username == null) {
+                throw new IllegalArgumentException("missing username");
+            }
+            if (params.realm == null) {
+                throw new IllegalArgumentException("missing realm");
+            }
+            if (params.uri == null) {
+                throw new IllegalArgumentException("missing uri");
+            }
+            if (params.nonce == null) {
+                throw new IllegalArgumentException("missing nonce");
+            }
+
+            A1 = params.username + ":" + params.realm + ":";
+            HashA1 = encode(A1, password, md);
+
+            String A2;
+            if (isRequest) {
+                A2 = reqMethod + ":" + params.uri;
+            } else {
+                A2 = ":" + params.uri;
+            }
+            String HashA2 = encode(A2, null, md);
+            String combo, finalHash;
+
+            if ("auth".equals(params.qop)) { /* RRC2617 when qop=auth */
+                if (params.cnonce == null) {
+                    throw new IllegalArgumentException("missing nonce");
+                }
+                if (params.nc == null) {
+                    throw new IllegalArgumentException("missing nonce");
+                }
+                combo = HashA1+ ":" + params.nonce + ":" + params.nc + ":" +
+                            params.cnonce + ":auth:" +HashA2;
+
+            } else { /* for compatibility with RFC2069 */
+                combo = HashA1 + ":" +
+                           params.nonce + ":" +
+                           HashA2;
+            }
+            finalHash = encode(combo, null, md);
+            return finalHash;
+        }
+
+        public static DigestResponse create(String raw) {
+            String username, realm, nonce, nc, uri, response, cnonce,
+                   algorithm, qop, opaque;
+            HeaderParser parser = new HeaderParser(raw);
+            username = parser.findValue("username");
+            realm = parser.findValue("realm");
+            nonce = parser.findValue("nonce");
+            nc = parser.findValue("nc");
+            uri = parser.findValue("uri");
+            cnonce = parser.findValue("cnonce");
+            response = parser.findValue("response");
+            algorithm = parser.findValue("algorithm");
+            qop = parser.findValue("qop");
+            opaque = parser.findValue("opaque");
+            return new DigestResponse(realm, username, nonce, cnonce, nc, uri,
+                                      algorithm, qop, opaque, response);
+        }
+
+    }
+
+    private class HttpNoAuthFilter extends AbstractHttpFilter {
+
+        public HttpNoAuthFilter(HttpAuthType authType) {
+            super(authType, authType == HttpAuthType.SERVER
+                            ? "NoAuth Server" : "NoAuth Proxy");
+        }
+
+        @Override
+        protected boolean isAuthentified(HttpExchange he) throws IOException {
+            return true;
+        }
+
+        @Override
+        protected void requestAuthentication(HttpExchange he) throws IOException {
+            throw new InternalError("Should not com here");
+        }
+
+        @Override
+        public String description() {
+            return "Passthrough Filter";
+        }
+
+    }
+
+    // An HTTP Filter that performs Basic authentication
+    private class HttpBasicFilter extends AbstractHttpFilter {
+
+        private final HttpTestAuthenticator auth;
+        public HttpBasicFilter(HttpTestAuthenticator auth, HttpAuthType authType) {
+            super(authType, authType == HttpAuthType.SERVER
+                            ? "Basic Server" : "Basic Proxy");
+            this.auth = auth;
+        }
+
+        @Override
+        protected void requestAuthentication(HttpExchange he)
+            throws IOException {
+            he.getResponseHeaders().add(getAuthenticate(),
+                 "Basic realm=\"" + auth.getRealm() + "\"");
+            System.out.println(type + ": Requesting Basic Authentication "
+                 + he.getResponseHeaders().getFirst(getAuthenticate()));
+        }
+
+        @Override
+        protected boolean isAuthentified(HttpExchange he) {
+            if (he.getRequestHeaders().containsKey(getAuthorization())) {
+                List<String> authorization =
+                    he.getRequestHeaders().get(getAuthorization());
+                for (String a : authorization) {
+                    System.out.println(type + ": processing " + a);
+                    int sp = a.indexOf(' ');
+                    if (sp < 0) return false;
+                    String scheme = a.substring(0, sp);
+                    if (!"Basic".equalsIgnoreCase(scheme)) {
+                        System.out.println(type + ": Unsupported scheme '"
+                                           + scheme +"'");
+                        return false;
+                    }
+                    if (a.length() <= sp+1) {
+                        System.out.println(type + ": value too short for '"
+                                            + scheme +"'");
+                        return false;
+                    }
+                    a = a.substring(sp+1);
+                    return validate(a);
+                }
+                return false;
+            }
+            return false;
+        }
+
+        boolean validate(String a) {
+            byte[] b = Base64.getDecoder().decode(a);
+            String userpass = new String (b);
+            int colon = userpass.indexOf (':');
+            String uname = userpass.substring (0, colon);
+            String pass = userpass.substring (colon+1);
+            return auth.getUserName().equals(uname) &&
+                   new String(auth.getPassword(uname)).equals(pass);
+        }
+
+        @Override
+        public String description() {
+            return "Filter for " + type;
+        }
+
+    }
+
+
+    // An HTTP Filter that performs Digest authentication
+    private class HttpDigestFilter extends AbstractHttpFilter {
+
+        // This is a very basic DIGEST - used only for the purpose of testing
+        // the client implementation. Therefore we can get away with never
+        // updating the server nonce as it makes the implementation of the
+        // server side digest simpler.
+        private final HttpTestAuthenticator auth;
+        private final byte[] nonce;
+        private final String ns;
+        public HttpDigestFilter(HttpTestAuthenticator auth, HttpAuthType authType) {
+            super(authType, authType == HttpAuthType.SERVER
+                            ? "Digest Server" : "Digest Proxy");
+            this.auth = auth;
+            nonce = new byte[16];
+            new Random(Instant.now().toEpochMilli()).nextBytes(nonce);
+            ns = new BigInteger(1, nonce).toString(16);
+        }
+
+        @Override
+        protected void requestAuthentication(HttpExchange he)
+            throws IOException {
+            he.getResponseHeaders().add(getAuthenticate(),
+                 "Digest realm=\"" + auth.getRealm() + "\","
+                 + "\r\n    qop=\"auth\","
+                 + "\r\n    nonce=\"" + ns +"\"");
+            System.out.println(type + ": Requesting Digest Authentication "
+                 + he.getResponseHeaders().getFirst(getAuthenticate()));
+        }
+
+        @Override
+        protected boolean isAuthentified(HttpExchange he) {
+            if (he.getRequestHeaders().containsKey(getAuthorization())) {
+                List<String> authorization = he.getRequestHeaders().get(getAuthorization());
+                for (String a : authorization) {
+                    System.out.println(type + ": processing " + a);
+                    int sp = a.indexOf(' ');
+                    if (sp < 0) return false;
+                    String scheme = a.substring(0, sp);
+                    if (!"Digest".equalsIgnoreCase(scheme)) {
+                        System.out.println(type + ": Unsupported scheme '" + scheme +"'");
+                        return false;
+                    }
+                    if (a.length() <= sp+1) {
+                        System.out.println(type + ": value too short for '" + scheme +"'");
+                        return false;
+                    }
+                    a = a.substring(sp+1);
+                    DigestResponse dgr = DigestResponse.create(a);
+                    return validate(he.getRequestMethod(), dgr);
+                }
+                return false;
+            }
+            return false;
+        }
+
+        boolean validate(String reqMethod, DigestResponse dg) {
+            if (!"MD5".equalsIgnoreCase(dg.getAlgorithm("MD5"))) {
+                System.out.println(type + ": Unsupported algorithm "
+                                   + dg.algorithm);
+                return false;
+            }
+            if (!"auth".equalsIgnoreCase(dg.getQoP("auth"))) {
+                System.out.println(type + ": Unsupported qop "
+                                   + dg.qop);
+                return false;
+            }
+            try {
+                if (!dg.nonce.equals(ns)) {
+                    System.out.println(type + ": bad nonce returned by client: "
+                                    + nonce + " expected " + ns);
+                    return false;
+                }
+                if (dg.response == null) {
+                    System.out.println(type + ": missing digest response.");
+                    return false;
+                }
+                char[] pa = auth.getPassword(dg.username);
+                return verify(reqMethod, dg, pa);
+            } catch(IllegalArgumentException | SecurityException
+                    | NoSuchAlgorithmException e) {
+                System.out.println(type + ": " + e.getMessage());
+                return false;
+            }
+        }
+
+        boolean verify(String reqMethod, DigestResponse dg, char[] pw)
+            throws NoSuchAlgorithmException {
+            String response = DigestResponse.computeDigest(true, reqMethod, pw, dg);
+            if (!dg.response.equals(response)) {
+                System.out.println(type + ": bad response returned by client: "
+                                    + dg.response + " expected " + response);
+                return false;
+            } else {
+                System.out.println(type + ": verified response " + response);
+            }
+            return true;
+        }
+
+        @Override
+        public String description() {
+            return "Filter for DIGEST authentication";
+        }
+    }
+
+    // Abstract HTTP handler class.
+    private abstract static class AbstractHttpHandler implements HttpHandler {
+
+        final HttpAuthType authType;
+        final String type;
+        public AbstractHttpHandler(HttpAuthType authType, String type) {
+            this.authType = authType;
+            this.type = type;
+        }
+
+        String getLocation() {
+            return "Location";
+        }
+
+        @Override
+        public void handle(HttpExchange he) throws IOException {
+            try {
+                sendResponse(he);
+            } catch (RuntimeException | Error | IOException t) {
+               System.err.println(type
+                    + ": Unexpected exception while handling request: " + t);
+               t.printStackTrace(System.err);
+               throw t;
+            } finally {
+                he.close();
+            }
+        }
+
+        protected abstract void sendResponse(HttpExchange he) throws IOException;
+
+    }
+
+    private class HttpNoAuthHandler extends AbstractHttpHandler {
+
+        public HttpNoAuthHandler(HttpAuthType authType) {
+            super(authType, authType == HttpAuthType.SERVER
+                            ? "NoAuth Server" : "NoAuth Proxy");
+        }
+
+        @Override
+        protected void sendResponse(HttpExchange he) throws IOException {
+            HTTPTestServer.this.writeResponse(he);
+        }
+
+    }
+
+    // A dummy HTTP Handler that redirects all incoming requests
+    // by sending a back 3xx response code (301, 305, 307 etc..)
+    private class Http3xxHandler extends AbstractHttpHandler {
+
+        private final URL redirectTargetURL;
+        private final int code3XX;
+        public Http3xxHandler(URL proxyURL, HttpAuthType authType, int code300) {
+            super(authType, "Server" + code300);
+            this.redirectTargetURL = proxyURL;
+            this.code3XX = code300;
+        }
+
+        int get3XX() {
+            return code3XX;
+        }
+
+        @Override
+        public void sendResponse(HttpExchange he) throws IOException {
+            System.out.println(type + ": Got " + he.getRequestMethod()
+                    + ": " + he.getRequestURI()
+                    + "\n" + HTTPTestServer.toString(he.getRequestHeaders()));
+            System.out.println(type + ": Redirecting to "
+                               + (authType == HttpAuthType.PROXY305
+                                    ? "proxy" : "server"));
+            he.getResponseHeaders().add(getLocation(),
+                redirectTargetURL.toExternalForm().toString());
+            he.sendResponseHeaders(get3XX(), 0);
+            System.out.println(type + ": Sent back " + get3XX() + " "
+                 + getLocation() + ": " + redirectTargetURL.toExternalForm().toString());
+        }
+    }
+
+    static class Configurator extends HttpsConfigurator {
+        public Configurator(SSLContext ctx) {
+            super(ctx);
+        }
+
+        @Override
+        public void configure (HttpsParameters params) {
+            params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+        }
+    }
+
+    // This is a bit hacky: HttpsProxyTunnel is an HTTPTestServer hidden
+    // behind a fake proxy that only understands CONNECT requests.
+    // The fake proxy is just a server socket that intercept the
+    // CONNECT and then redirect streams to the real server.
+    static class HttpsProxyTunnel extends HTTPTestServer
+            implements Runnable {
+
+        final ServerSocket ss;
+        public HttpsProxyTunnel(HttpServer server, HTTPTestServer target,
+                               HttpHandler delegate)
+                throws IOException {
+            super(server, target, delegate);
+            System.out.flush();
+            System.err.println("WARNING: HttpsProxyTunnel is an experimental test class");
+            ss = new ServerSocket(0, 0, InetAddress.getByName("127.0.0.1"));
+            start();
+        }
+
+        final void start() throws IOException {
+            Thread t = new Thread(this, "ProxyThread");
+            t.setDaemon(true);
+            t.start();
+        }
+
+        @Override
+        public void stop() {
+            super.stop();
+            try {
+                ss.close();
+            } catch (IOException ex) {
+                if (DEBUG) ex.printStackTrace(System.out);
+            }
+        }
+
+        // Pipe the input stream to the output stream.
+        private synchronized Thread pipe(InputStream is, OutputStream os, char tag) {
+            return new Thread("TunnelPipe("+tag+")") {
+                @Override
+                public void run() {
+                    try {
+                        try {
+                            int c;
+                            while ((c = is.read()) != -1) {
+                                os.write(c);
+                                os.flush();
+                                // if DEBUG prints a + or a - for each transferred
+                                // character.
+                                if (DEBUG) System.out.print(tag);
+                            }
+                            is.close();
+                        } finally {
+                            os.close();
+                        }
+                    } catch (IOException ex) {
+                        if (DEBUG) ex.printStackTrace(System.out);
+                    }
+                }
+            };
+        }
+
+        @Override
+        public InetSocketAddress getAddress() {
+            return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort());
+        }
+
+        // This is a bit shaky. It doesn't handle continuation
+        // lines, but our client shouldn't send any.
+        // Read a line from the input stream, swallowing the final
+        // \r\n sequence. Stops at the first \n, doesn't complain
+        // if it wasn't preceded by '\r'.
+        //
+        String readLine(InputStream r) throws IOException {
+            StringBuilder b = new StringBuilder();
+            int c;
+            while ((c = r.read()) != -1) {
+                if (c == '\n') break;
+                b.appendCodePoint(c);
+            }
+            if (b.codePointAt(b.length() -1) == '\r') {
+                b.delete(b.length() -1, b.length());
+            }
+            return b.toString();
+        }
+
+        @Override
+        public void run() {
+            Socket clientConnection = null;
+            try {
+                while (true) {
+                    System.out.println("Tunnel: Waiting for client");
+                    Socket previous = clientConnection;
+                    try {
+                        clientConnection = ss.accept();
+                    } catch (IOException io) {
+                        if (DEBUG) io.printStackTrace(System.out);
+                        break;
+                    } finally {
+                        // close the previous connection
+                        if (previous != null) previous.close();
+                    }
+                    System.out.println("Tunnel: Client accepted");
+                    Socket targetConnection = null;
+                    InputStream  ccis = clientConnection.getInputStream();
+                    OutputStream ccos = clientConnection.getOutputStream();
+                    Writer w = new OutputStreamWriter(
+                                   clientConnection.getOutputStream(), "UTF-8");
+                    PrintWriter pw = new PrintWriter(w);
+                    System.out.println("Tunnel: Reading request line");
+                    String requestLine = readLine(ccis);
+                    System.out.println("Tunnel: Request line: " + requestLine);
+                    if (requestLine.startsWith("CONNECT ")) {
+                        // We should probably check that the next word following
+                        // CONNECT is the host:port of our HTTPS serverImpl.
+                        // Some improvement for a followup!
+
+                        // Read all headers until we find the empty line that
+                        // signals the end of all headers.
+                        while(!requestLine.equals("")) {
+                            System.out.println("Tunnel: Reading header: "
+                                               + (requestLine = readLine(ccis)));
+                        }
+
+                        targetConnection = new Socket(
+                                serverImpl.getAddress().getAddress(),
+                                serverImpl.getAddress().getPort());
+
+                        // Then send the 200 OK response to the client
+                        System.out.println("Tunnel: Sending "
+                                           + "HTTP/1.1 200 OK\r\n\r\n");
+                        pw.print("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
+                        pw.flush();
+                    } else {
+                        // This should not happen. If it does let our serverImpl
+                        // deal with it.
+                        throw new IOException("Tunnel: Unexpected status line: "
+                                             + requestLine);
+                    }
+
+                    // Pipe the input stream of the client connection to the
+                    // output stream of the target connection and conversely.
+                    // Now the client and target will just talk to each other.
+                    System.out.println("Tunnel: Starting tunnel pipes");
+                    Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+');
+                    Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-');
+                    t1.start();
+                    t2.start();
+
+                    // We have only 1 client... wait until it has finished before
+                    // accepting a new connection request.
+                    t1.join();
+                    t2.join();
+                }
+            } catch (Throwable ex) {
+                try {
+                    ss.close();
+                } catch (IOException ex1) {
+                    ex.addSuppressed(ex1);
+                }
+                ex.printStackTrace(System.err);
+            }
+        }
+
+    }
+}
diff --git a/jdk/test/java/net/HttpURLConnection/getResponseCode.java b/jdk/test/java/net/HttpURLConnection/getResponseCode.java
index eb6a64d..4eca0d5 100644
--- a/jdk/test/java/net/HttpURLConnection/getResponseCode.java
+++ b/jdk/test/java/net/HttpURLConnection/getResponseCode.java
@@ -24,6 +24,8 @@
 /*
  * @test
  * @bug 4666195
+ * @build getResponseCode
+ * @run main getResponseCode
  * @summary REGRESSION: HttpURLConnection.getResponseCode() returns always -1
 */
 import java.net.*;
diff --git a/jdk/test/java/net/InterfaceAddress/Equals.java b/jdk/test/java/net/InterfaceAddress/Equals.java
index 16511d5..b12e084 100644
--- a/jdk/test/java/net/InterfaceAddress/Equals.java
+++ b/jdk/test/java/net/InterfaceAddress/Equals.java
@@ -23,6 +23,7 @@
 
 /* @test
  * @bug 6628576
+ * @modules java.base/java.net:open
  * @summary InterfaceAddress.equals() NPE when broadcast field == null
  */
 
diff --git a/jdk/test/java/nio/Buffer/Basic.java b/jdk/test/java/nio/Buffer/Basic.java
index 957d1fc..7d5f85e 100644
--- a/jdk/test/java/nio/Buffer/Basic.java
+++ b/jdk/test/java/nio/Buffer/Basic.java
@@ -27,7 +27,8 @@
  *      4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
  *      6221101 6234263 6535542 6591971 6593946 6795561 7190219 7199551 8065556
  *      8149469
- * @modules java.base/jdk.internal.misc
+ * @modules java.base/java.nio:open
+ *          java.base/jdk.internal.misc
  * @author Mark Reinhold
  */
 
diff --git a/jdk/test/java/nio/channels/Selector/TemporarySelector.java b/jdk/test/java/nio/channels/Selector/TemporarySelector.java
index c131c32..fe2a555 100644
--- a/jdk/test/java/nio/channels/Selector/TemporarySelector.java
+++ b/jdk/test/java/nio/channels/Selector/TemporarySelector.java
@@ -23,7 +23,7 @@
 
 /* @test
  * @bug 6645197
- * @run main/othervm -Xmx5m TemporarySelector
+ * @run main/othervm -Xmx16m TemporarySelector
  * @summary Timed read with socket adaptor throws ClosedSelectorException if temporary selector GC'ed.
  */
 import java.io.IOException;
diff --git a/jdk/test/java/nio/channels/Selector/Wakeup.java b/jdk/test/java/nio/channels/Selector/Wakeup.java
index 40aa717..8caacbb 100644
--- a/jdk/test/java/nio/channels/Selector/Wakeup.java
+++ b/jdk/test/java/nio/channels/Selector/Wakeup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,14 +24,14 @@
 /* @test
  * @bug 6405995
  * @summary Unit test for selector wakeup and interruption
- * @library ..
+ * @library .. /lib/testlibrary/
  */
 
 import java.io.*;
 import java.net.*;
 import java.nio.*;
 import java.nio.channels.*;
-import java.util.Random;
+import java.util.concurrent.CyclicBarrier;
 
 public class Wakeup {
 
@@ -44,91 +44,112 @@
     }
 
     static class Sleeper extends TestThread {
+        private static final long TIMEOUT = jdk.testlibrary.Utils.adjustTimeout(20_000);
+
+        // barrier is used to synchronize sleeper thread and checking
+        // thread which is the main thread: when go() get to the end,
+        // then start checking the sleeper's status.
+        private static CyclicBarrier barrier = new CyclicBarrier(2);
+        private static int wakeups = 0;
+        private static int waits = 0;
+
+        volatile boolean interruptBeforeSelect = false;
         volatile boolean started = false;
-        volatile int entries = 0;
-        volatile int wakeups = 0;
         volatile boolean wantInterrupt = false;
-        volatile boolean gotInterrupt = false;
-        volatile Exception exception = null;
         volatile boolean closed = false;
         Object gate = new Object();
 
         Selector sel;
 
-        Sleeper(Selector sel) {
+        Sleeper(Selector sel, boolean wantInterrupt, boolean interruptBeforeSelect) {
             super("Sleeper", System.err);
             this.sel = sel;
+            this.wantInterrupt = wantInterrupt;
+            this.interruptBeforeSelect = interruptBeforeSelect;
         }
 
         public void go() throws Exception {
             started = true;
-            for (;;) {
+            if (interruptBeforeSelect) {
                 synchronized (gate) { }
-                entries++;
-                try {
-                    sel.select();
-                } catch (ClosedSelectorException x) {
-                    closed = true;
-                }
-                boolean intr = Thread.currentThread().isInterrupted();
-                wakeups++;
-                System.err.println("Wakeup " + wakeups
-                                   + (closed ? " (closed)" : "")
-                                   + (intr ? " (intr)" : ""));
-                if (wakeups > 1000)
-                    throw new Exception("Too many wakeups");
-                if (closed)
-                    return;
-                if (wantInterrupt) {
-                    while (!Thread.interrupted())
-                        Thread.yield();
-                    gotInterrupt = true;
-                    wantInterrupt = false;
-                }
             }
+            wakeups++;
+            System.err.println("Wakeup, selecting, " + wakeups);
+            try {
+                sel.select();
+            } catch (ClosedSelectorException x) {
+                closed = true;
+            }
+            boolean intr = Thread.currentThread().isInterrupted();
+            System.err.println("Wakeup " + wakeups
+                               + (closed ? " (closed)" : "")
+                               + (intr ? " (intr)" : ""));
+            if (closed)
+                return;
+            if (wantInterrupt) {
+                while (!Thread.interrupted())
+                    Thread.yield();
+            }
+            System.err.println("Wakeup, waiting, " + wakeups);
+            barrier.await();
+            System.err.println("Wakeup, wait successfully, " + wakeups);
         }
 
+        void check(boolean close) throws Exception {
+            waits++;
+            System.err.println("waiting sleeper, " + waits);
+            if (!close) {
+                barrier.await();
+                System.err.println("wait barrier successfully, " + waits);
+            }
+            if (finish(TIMEOUT) == 0)
+                throw new Exception("Test failed");
+            if (this.closed != close)
+                throw new Exception("Selector was closed");
+        }
+
+        void check() throws Exception {
+            check(false);
+        }
+
+        static Sleeper createSleeper(Selector sel, boolean wantInterrupt,
+                boolean interruptBeforeSelect) throws Exception {
+            if (!wantInterrupt && interruptBeforeSelect) {
+                throw new RuntimeException("Wrong parameters!");
+            }
+
+            Sleeper sleeper = new Sleeper(sel, wantInterrupt, interruptBeforeSelect);
+
+            if (interruptBeforeSelect) {
+                synchronized(sleeper.gate) {
+                    sleeper.start();
+                    while (!sleeper.started)
+                        sleep(50);
+                    sleeper.interrupt();
+                }
+            } else {
+                sleeper.start();
+                while (!sleeper.started)
+                    sleep(50);
+                if (wantInterrupt) {
+                    sleep(50);
+                    sleeper.interrupt();
+                }
+            }
+            return sleeper;
+        }
     }
 
-    private static int checkedWakeups = 0;
+    static Sleeper newSleeper(Selector sel) throws Exception {
+        return Sleeper.createSleeper(sel, false, false);
+    }
 
-    private static void check(Sleeper sleeper, boolean intr)
-        throws Exception
-    {
-        checkedWakeups++;
-        if (sleeper.wakeups > checkedWakeups) {
-            sleeper.finish(100);
-            throw new Exception("Sleeper has run ahead");
-        }
-        int n = 0;
-        while (sleeper.wakeups < checkedWakeups) {
-            sleep(50);
-            if ((n += 50) > 1000) {
-                sleeper.finish(100);
-                throw new Exception("Sleeper appears to be dead ("
-                                    + checkedWakeups + ")");
-            }
-        }
-        if (sleeper.wakeups > checkedWakeups) {
-            sleeper.finish(100);
-            throw new Exception("Too many wakeups: Expected "
-                                + checkedWakeups
-                                + ", got " + sleeper.wakeups);
-        }
-        if (intr) {
-            n = 0;
-            // Interrupts can sometimes be delayed, so wait
-            while (!sleeper.gotInterrupt) {
-                sleep(50);
-                if ((n += 50) > 1000) {
-                    sleeper.finish(100);
-                    throw new Exception("Interrupt never delivered");
-                }
-            }
-            sleeper.gotInterrupt = false;
-        }
-        System.err.println("Check " + checkedWakeups
-                           + (intr ? " (intr " + n + ")" : ""));
+    static Sleeper newSleeperWantInterrupt(Selector sel) throws Exception {
+        return Sleeper.createSleeper(sel, true, false);
+    }
+
+    static Sleeper newSleeperWantInterruptBeforeSelect(Selector sel) throws Exception {
+        return Sleeper.createSleeper(sel, true, true);
     }
 
     public static void main(String[] args) throws Exception {
@@ -138,60 +159,37 @@
         // Wakeup before select
         sel.wakeup();
 
-        Sleeper sleeper = new Sleeper(sel);
-
-        sleeper.start();
-        while (!sleeper.started)
-            sleep(50);
-
-        check(sleeper, false);          // 1
+        Sleeper sleeper = newSleeper(sel); // 1
+        sleeper.check();
 
         for (int i = 2; i < 5; i++) {
             // Wakeup during select
+            sleeper = newSleeper(sel);
             sel.wakeup();
-            check(sleeper, false);      // 2 .. 4
+            sleeper.check();         // 2 .. 4
         }
 
         // Double wakeup
-        synchronized (sleeper.gate) {
-            sel.wakeup();
-            check(sleeper, false);      // 5
-            sel.wakeup();
-            sel.wakeup();
-        }
-        check(sleeper, false);          // 6
+        sel.wakeup();
+        sel.wakeup();
+        sleeper = newSleeper(sel);
+        sleeper.check();            // 5
 
         // Interrupt
-        synchronized (sleeper.gate) {
-            sleeper.wantInterrupt = true;
-            sleeper.interrupt();
-            check(sleeper, true);       // 7
-        }
+        sleeper = newSleeperWantInterrupt(sel);
+        sleeper.check();            // 6
 
         // Interrupt before select
-        while (sleeper.entries < 8)
-            Thread.yield();
-        synchronized (sleeper.gate) {
-            sel.wakeup();
-            check(sleeper, false);      // 8
-            sleeper.wantInterrupt = true;
-            sleeper.interrupt();
-            sleep(50);
-        }
-        check(sleeper, true);           // 9
+        sleeper = newSleeperWantInterruptBeforeSelect(sel);
+        sleeper.check();            // 7
 
         // Close during select
-        while (sleeper.entries < 10)
-            Thread.yield();
-        synchronized (sleeper.gate) {
-            sel.close();
-            check(sleeper, false);      // 10
-        }
+        sleeper = newSleeper(sel);
+        sel.close();
+        sleeper.check();           // 8
 
-        if (sleeper.finish(200) == 0)
-            throw new Exception("Test failed");
-        if (!sleeper.closed)
-            throw new Exception("Selector not closed");
+        sleeper = newSleeper(sel);
+        sleeper.check(true);
     }
 
 }
diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh
index 46ecc31..9b01503 100644
--- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh
+++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh
@@ -109,7 +109,8 @@
 
 go() {
     echo ''
-    sh -xc "$JAVA ${TESTVMOPTS} --add-exports java.base/sun.nio.ch=ALL-UNNAMED $DFLAG \
+    sh -xc "$JAVA ${TESTVMOPTS} --add-opens java.base/java.io=ALL-UNNAMED \
+            --add-opens java.base/sun.nio.ch=ALL-UNNAMED $DFLAG \
         $1 $2 $3 $4 $5 $6 $7 $8" 2>&1
     if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
 }
diff --git a/jdk/test/java/nio/file/etc/Exceptions.java b/jdk/test/java/nio/file/etc/Exceptions.java
index 28d9459..b1feae2 100644
--- a/jdk/test/java/nio/file/etc/Exceptions.java
+++ b/jdk/test/java/nio/file/etc/Exceptions.java
@@ -23,6 +23,7 @@
 
 /* @test
  * @bug 4313887 6881498
+ * @modules java.base/java.lang:open
  * @summary Miscellenous tests on exceptions in java.nio.file
  */
 
diff --git a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java
index 85e22e4..9311879 100644
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java
@@ -37,7 +37,7 @@
  *
  * @library ../../../testlibrary
  * @modules java.rmi/sun.rmi.registry
- *          java.rmi/sun.rmi.server
+ *          java.rmi/sun.rmi.server:+open
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
  *          java.base/sun.nio.ch
diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java
index 721ecf8..e282683 100644
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,9 +93,8 @@
             obj = new CallbackImpl();
             Callback proxy =
                 (Callback) UnicastRemoteObject.exportObject(obj, 0);
-            Registry registry =
-                LocateRegistry.createRegistry(
-                    TestLibrary.INHERITEDCHANNELNOTSERVERSOCKET_REGISTRY_PORT);
+            Registry registry = TestLibrary.createRegistryOnEphemeralPort();
+            int registryPort = TestLibrary.getRegistryPort(registry);
             registry.bind("Callback", proxy);
 
             /*
@@ -107,7 +106,8 @@
                                    TestLibrary.INHERITEDCHANNELNOTSERVERSOCKET_ACTIVATION_PORT);
             rmid.addOptions(
                 "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED",
-                "-Djava.nio.channels.spi.SelectorProvider=InheritedChannelNotServerSocket$SP");
+                "-Djava.nio.channels.spi.SelectorProvider=InheritedChannelNotServerSocket$SP",
+                "-Dtest.java.rmi.rmidViaInheritedChannel.registry.port=" + registryPort);
             rmid.start();
 
             /*
@@ -181,8 +181,9 @@
                  */
                 try {
                     System.err.println("notify test...");
-                    Registry registry =
-                        LocateRegistry.getRegistry(TestLibrary.INHERITEDCHANNELNOTSERVERSOCKET_REGISTRY_PORT);
+                    int registryPort = Integer.getInteger(
+                            "test.java.rmi.rmidViaInheritedChannel.registry.port", 0);
+                    Registry registry = LocateRegistry.getRegistry(registryPort);
                     Callback obj = (Callback) registry.lookup("Callback");
                     obj.notifyTest();
                 } catch (NotBoundException nbe) {
diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java
deleted file mode 100644
index 4d27bc8..0000000
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @bug 4295885 6824141
- * @summary rmid should be startable from inetd
- * @author Ann Wollrath
- *
- * @library ../../testlibrary
- * @modules java.base/sun.nio.ch
- *          java.rmi/sun.rmi.registry
- *          java.rmi/sun.rmi.server
- *          java.rmi/sun.rmi.transport
- *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
- * @run main/othervm/timeout=240 RmidViaInheritedChannel
- * @key intermittent
- */
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.ProtocolFamily;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.rmi.Remote;
-import java.rmi.NotBoundException;
-import java.rmi.activation.ActivationGroup;
-import java.rmi.activation.ActivationSystem;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-import static java.net.StandardSocketOptions.SO_REUSEADDR;
-import static java.net.StandardSocketOptions.SO_REUSEPORT;
-
-public class RmidViaInheritedChannel implements Callback {
-    private static final Object lock = new Object();
-    private static boolean notified = false;
-
-    private RmidViaInheritedChannel() {}
-
-    public void notifyTest() {
-        synchronized (lock) {
-            notified = true;
-            System.err.println("notification received.");
-            lock.notifyAll();
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.setProperty("java.rmi.activation.port",
-                           Integer.toString(TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT));
-        RMID rmid = null;
-        Callback obj = null;
-
-        try {
-            /*
-             * Export callback object and bind in registry.
-             */
-            System.err.println("export callback object and bind in registry");
-            obj = new RmidViaInheritedChannel();
-            Callback proxy = (Callback)
-                UnicastRemoteObject.exportObject(obj, 0);
-            Registry registry =
-                LocateRegistry.createRegistry(
-                    TestLibrary.RMIDVIAINHERITEDCHANNEL_REGISTRY_PORT);
-            registry.bind("Callback", proxy);
-
-            /*
-             * Start rmid.
-             */
-            System.err.println("start rmid with inherited channel");
-            RMID.removeLog();
-            rmid = RMID.createRMID(System.out, System.err, true, false,
-                                   TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT);
-            rmid.addOptions(
-                "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED",
-                "-Djava.nio.channels.spi.SelectorProvider=RmidViaInheritedChannel$RmidSelectorProvider");
-            if (System.getProperty("os.name").startsWith("Windows") &&
-                System.getProperty("os.version").startsWith("5."))
-            {
-                /* Windows XP/2003 or older
-                 * Need to expand ephemeral range to include RMI test ports
-                 */
-                rmid.addOptions(new String[]{
-                    "-Djdk.net.ephemeralPortRange.low=1024",
-                    "-Djdk.net.ephemeralPortRange.high=64000"
-                });
-            }
-            rmid.start();
-
-            /*
-             * Get activation system and wait to be notified via callback
-             * from rmid's selector provider.
-             */
-            System.err.println("get activation system");
-            ActivationSystem system = ActivationGroup.getSystem();
-            System.err.println("ActivationSystem = " + system);
-            synchronized (lock) {
-                while (!notified) {
-                    lock.wait();
-                }
-            }
-            System.err.println("TEST PASSED");
-
-        } finally {
-            if (obj != null) {
-                UnicastRemoteObject.unexportObject(obj, true);
-            }
-            if (rmid != null) {
-                rmid.cleanup();
-            }
-        }
-    }
-
-    public static class RmidSelectorProvider extends SelectorProvider {
-
-        private final SelectorProvider provider;
-        private ServerSocketChannel channel = null;
-
-        public RmidSelectorProvider() {
-            provider =  sun.nio.ch.DefaultSelectorProvider.create();
-        }
-
-        public DatagramChannel openDatagramChannel()
-            throws IOException
-        {
-            return provider.openDatagramChannel();
-        }
-
-        public DatagramChannel openDatagramChannel(ProtocolFamily family)
-            throws IOException
-        {
-            return provider.openDatagramChannel(family);
-        }
-
-        public Pipe openPipe()
-            throws IOException
-        {
-            return provider.openPipe();
-        }
-
-        public AbstractSelector openSelector()
-            throws IOException
-        {
-            return provider.openSelector();
-        }
-
-        public ServerSocketChannel openServerSocketChannel()
-            throws IOException
-        {
-            return provider.openServerSocketChannel();
-        }
-
-        public SocketChannel openSocketChannel()
-             throws IOException
-        {
-            return provider.openSocketChannel();
-        }
-
-        public synchronized Channel inheritedChannel() throws IOException {
-            System.err.println("RmidSelectorProvider.inheritedChannel");
-            if (channel == null) {
-                /*
-                 * Create server socket channel and bind server socket.
-                 */
-                channel = ServerSocketChannel.open();
-                ServerSocket serverSocket = channel.socket();
-
-                // Enable SO_REUSEADDR before binding
-                serverSocket.setOption(SO_REUSEADDR, true);
-
-                // Enable SO_REUSEPORT, if supported, before binding
-                if (serverSocket.supportedOptions().contains(SO_REUSEPORT)) {
-                    serverSocket.setOption(SO_REUSEPORT, true);
-                }
-
-                serverSocket.bind(
-                     new InetSocketAddress(InetAddress.getLocalHost(),
-                     TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT));
-                System.err.println("serverSocket = " + serverSocket);
-
-                /*
-                 * Notify test that inherited channel was created.
-                 */
-                try {
-                    System.err.println("notify test...");
-                    Registry registry =
-                        LocateRegistry.getRegistry(TestLibrary.RMIDVIAINHERITEDCHANNEL_REGISTRY_PORT);
-                    Callback obj = (Callback) registry.lookup("Callback");
-                    obj.notifyTest();
-                } catch (NotBoundException nbe) {
-                    throw (IOException)
-                        new IOException("callback object not bound").
-                            initCause(nbe);
-                }
-            }
-            return channel;
-        }
-    }
-}
-
-interface Callback extends Remote {
-    void notifyTest() throws IOException;
-}
diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/rmid.security.policy b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/rmid.security.policy
index 9ddb556..1d94a37 100644
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/rmid.security.policy
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/rmid.security.policy
@@ -3,4 +3,5 @@
     permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
     permission java.net.SocketPermission "*", "connect,accept";
     permission java.util.PropertyPermission "java.rmi.activation.port", "write";
+    permission java.util.PropertyPermission "test.java.rmi.rmidViaInheritedChannel.registry.port", "read";
 };
diff --git a/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java b/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
index f30be86..bb0394a 100644
--- a/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
+++ b/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
@@ -30,7 +30,7 @@
  * rather than pinning it indefinitely.
  * @author Peter Jones
  *
- * @modules java.rmi/sun.rmi.transport
+ * @modules java.rmi/sun.rmi.transport:+open
  * @build DGCAckFailure DGCAckFailure_Stub
  * @run main/othervm DGCAckFailure
  */
diff --git a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java
index b324666..82a9554 100644
--- a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java
+++ b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,6 @@
  *          java.rmi/sun.rmi.transport.tcp
  * @build TestLibrary ReferenceRegistryStub
  * @run main/othervm InterfaceHash
- * @key intermittent
  */
 
 import java.lang.reflect.Constructor;
@@ -63,7 +62,6 @@
 
 public class InterfaceHash {
 
-    private static final int PORT = TestLibrary.getUnusedRandomPort();
     private static final String NAME = "WMM";
 
     public static void main(String[] args) throws Exception {
@@ -73,12 +71,13 @@
             "\n=== verifying that J2SE registry's skeleton uses" +
             "\ncorrect interface hash and operation numbers:");
 
-        Registry testImpl = LocateRegistry.createRegistry(PORT);
-        System.err.println("created test registry on port " + PORT);
+        Registry testImpl = TestLibrary.createRegistryOnEphemeralPort();
+        int regPort = TestLibrary.getRegistryPort(testImpl);
+        System.err.println("created test registry on port " + regPort);
 
         RemoteRef ref = new UnicastRef(
             new LiveRef(new ObjID(ObjID.REGISTRY_ID),
-                        new TCPEndpoint("", PORT), false));
+                        new TCPEndpoint("", regPort), false));
         Registry referenceStub = new ReferenceRegistryStub(ref);
         System.err.println("created reference registry stub: " +
                            referenceStub);
@@ -144,7 +143,7 @@
         }
         FakeRemoteRef f = new FakeRemoteRef();
 
-        Registry testRegistry = LocateRegistry.getRegistry(PORT);
+        Registry testRegistry = LocateRegistry.getRegistry(regPort);
         System.err.println("created original test registry stub: " +
                            testRegistry);
 
diff --git a/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnlyDefault/UseCodebaseOnlyDefault.java b/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnlyDefault/UseCodebaseOnlyDefault.java
index 6520d26..7fc99f4 100644
--- a/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnlyDefault/UseCodebaseOnlyDefault.java
+++ b/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnlyDefault/UseCodebaseOnlyDefault.java
@@ -27,7 +27,7 @@
  * @summary Tests proper parsing and defaulting of the
  * "java.rmi.server.useCodebaseOnly" property.
  *
- * @modules java.rmi/sun.rmi.server
+ * @modules java.rmi/sun.rmi.server:+open
  * @run main/othervm UseCodebaseOnlyDefault true
  * @run main/othervm -Djava.rmi.server.useCodebaseOnly=xyzzy UseCodebaseOnlyDefault true
  * @run main/othervm -Djava.rmi.server.useCodebaseOnly UseCodebaseOnlyDefault true
diff --git a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java
index 889a55e..3b61bb1 100644
--- a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java
+++ b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java
@@ -43,7 +43,6 @@
  *          java.rmi/sun.rmi.transport.tcp
  * @build TestLibrary JavaVM LeaseCheckInterval_Stub SelfTerminator
  * @run main/othervm LeaseCheckInterval
- * @key intermittent
  */
 
 import java.rmi.Remote;
@@ -88,9 +87,8 @@
             UnicastRemoteObject.exportObject(obj);
             System.err.println("exported remote object");
 
-            int registryPort = TestLibrary.getUnusedRandomPort();
-            Registry localRegistry =
-                LocateRegistry.createRegistry(registryPort);
+            Registry localRegistry = TestLibrary.createRegistryOnEphemeralPort();
+            int registryPort = TestLibrary.getRegistryPort(localRegistry);
             System.err.println("created local registry");
 
             localRegistry.bind(BINDING, obj);
diff --git a/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java b/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java
index ee2df0537..a624597 100644
--- a/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java
+++ b/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java
@@ -29,7 +29,7 @@
  *
  * @library ../../testlibrary
  * @modules java.rmi/sun.rmi.registry
- *          java.rmi/sun.rmi.server
+ *          java.rmi/sun.rmi.server:+open
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
  * @build TestLibrary
diff --git a/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java b/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java
index bbb271c..a62cfad 100644
--- a/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java
+++ b/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -86,7 +86,7 @@
 
             System.err.println("creating Registry...");
 
-            registry = TestLibrary.createRegistryOnUnusedPort();
+            registry = TestLibrary.createRegistryOnEphemeralPort();
             int port = TestLibrary.getRegistryPort(registry);
             /*
              * create object with custom ref and bind in registry
diff --git a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
index 181b1d0..5e0f69a 100644
--- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
@@ -77,7 +77,7 @@
                 TestParams.defaultPolicy +
                 " --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-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" +
                 " --add-exports java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
                 " -Djava.rmi.dgc.leaseValue=500000" +
                 "  -Dsun.rmi.dgc.checkInterval=" +
diff --git a/jdk/test/java/security/SecureRandom/ApiTest.java b/jdk/test/java/security/SecureRandom/ApiTest.java
index fb2e355..73fae8b 100644
--- a/jdk/test/java/security/SecureRandom/ApiTest.java
+++ b/jdk/test/java/security/SecureRandom/ApiTest.java
@@ -195,10 +195,10 @@
             case "AES-128":
             case "AES-192":
             case "AES-256":
-                int algoStrength = Integer.parseInt(alg.replaceAll("AES-", ""));
-                int maxStrengthSupported = Cipher.getMaxAllowedKeyLength("AES");
-                if (strength > maxStrengthSupported
-                        || algoStrength > maxStrengthSupported) {
+                int algoStrength = Integer.parseInt(alg.substring("AES-".length()));
+                int maxAESStrength = Cipher.getMaxAllowedKeyLength("AES");
+                if (strength > algoStrength
+                        || algoStrength > maxAESStrength) {
                     error = false;
                 }
                 break;
diff --git a/jdk/test/java/security/modules/ModularTest.java b/jdk/test/java/security/modules/ModularTest.java
index 356bb08..9e67094 100644
--- a/jdk/test/java/security/modules/ModularTest.java
+++ b/jdk/test/java/security/modules/ModularTest.java
@@ -164,7 +164,7 @@
         final Builder builder;
         if (moduleType == MODULE_TYPE.EXPLICIT) {
             System.out.format(" %nGenerating ModuleDescriptor object");
-            builder = new Builder(moduleName).exports(pkg);
+            builder = ModuleDescriptor.module(moduleName).exports(pkg);
             if (isService && serviceInterface != null && serviceImpl != null) {
                 builder.provides(serviceInterface, serviceImpl);
             } else {
diff --git a/jdk/test/java/security/testlibrary/Proc.java b/jdk/test/java/security/testlibrary/Proc.java
index ec5fae6..7248757 100644
--- a/jdk/test/java/security/testlibrary/Proc.java
+++ b/jdk/test/java/security/testlibrary/Proc.java
@@ -257,7 +257,8 @@
 
         if (hasModules) {
             Stream.of(jdk.internal.misc.VM.getRuntimeArguments())
-                    .filter(arg -> arg.startsWith("--add-exports="))
+                    .filter(arg -> arg.startsWith("--add-exports=") ||
+                                   arg.startsWith("--add-opens="))
                     .forEach(cmd::add);
         }
 
diff --git a/jdk/test/java/time/TEST.properties b/jdk/test/java/time/TEST.properties
index 8222402..49d8c3c 100644
--- a/jdk/test/java/time/TEST.properties
+++ b/jdk/test/java/time/TEST.properties
@@ -4,3 +4,4 @@
 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
diff --git a/jdk/test/java/util/ArrayList/ArrayManagement.java b/jdk/test/java/util/ArrayList/ArrayManagement.java
index 81adc71..e63a25a 100644
--- a/jdk/test/java/util/ArrayList/ArrayManagement.java
+++ b/jdk/test/java/util/ArrayList/ArrayManagement.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 8146568
  * @summary brittle white box test of internal array management
+ * @modules java.base/java.util:open
  * @run testng ArrayManagement
  */
 
diff --git a/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.java b/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.java
index 308f294..03d0e3d 100644
--- a/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.java
+++ b/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.java
@@ -22,21 +22,36 @@
  */
 
 /*
- * This is not a regression test, but a micro-benchmark.
- * Be patient; this runs for half an hour!
+ * @test
+ * @summary micro-benchmark correctness mode
+ * @run main IteratorMicroBenchmark iterations=1 size=8 warmup=0
+ */
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Spliterator;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+/**
+ * Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
  *
- * I have run this as follows:
- *
- * for f in -client -server; do mergeBench dolphin . jr -dsa -da $f IteratorMicroBenchmark.java; done
- *
+ * To run this in micro-benchmark mode, simply run as a normal java program.
+ * Be patient; this program runs for a very long time.
+ * For faster runs, restrict execution using command line args.
  *
  * @author Martin Buchholz
  */
-
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.regex.Pattern;
-
 public class IteratorMicroBenchmark {
     abstract static class Job {
         private final String name;
@@ -45,17 +60,28 @@
         public abstract void work() throws Throwable;
     }
 
-    private static void collectAllGarbage() {
-        final java.util.concurrent.CountDownLatch drained
-            = new java.util.concurrent.CountDownLatch(1);
+    static double warmupSeconds;
+    static long warmupNanos;
+
+    // --------------- GC finalization infrastructure ---------------
+
+    /** No guarantees, but effective in practice. */
+    static void forceFullGc() {
+        CountDownLatch finalizeDone = new CountDownLatch(1);
+        WeakReference<?> ref = new WeakReference<Object>(new Object() {
+            protected void finalize() { finalizeDone.countDown(); }});
         try {
-            System.gc();        // enqueue finalizable objects
-            new Object() { protected void finalize() {
-                drained.countDown(); }};
-            System.gc();        // enqueue detector
-            drained.await();    // wait for finalizer queue to drain
-            System.gc();        // cleanup finalized objects
-        } catch (InterruptedException e) { throw new Error(e); }
+            for (int i = 0; i < 10; i++) {
+                System.gc();
+                if (finalizeDone.await(1L, TimeUnit.SECONDS) && ref.get() == null) {
+                    System.runFinalization(); // try to pick up stragglers
+                    return;
+                }
+            }
+        } catch (InterruptedException unexpected) {
+            throw new AssertionError("unexpected InterruptedException");
+        }
+        throw new AssertionError("failed to do a \"full\" gc");
     }
 
     /**
@@ -65,23 +91,22 @@
      * Returns array of average times per job per run.
      */
     private static long[] time0(Job ... jobs) throws Throwable {
-        final long warmupNanos = 10L * 1000L * 1000L * 1000L;
         long[] nanoss = new long[jobs.length];
         for (int i = 0; i < jobs.length; i++) {
-            collectAllGarbage();
-            long t0 = System.nanoTime();
-            long t;
-            int j = 0;
-            do { jobs[i].work(); j++; }
-            while ((t = System.nanoTime() - t0) < warmupNanos);
-            nanoss[i] = t/j;
+            if (warmupNanos > 0) forceFullGc();
+            Job job = jobs[i];
+            long totalTime;
+            int runs = 0;
+            long startTime = System.nanoTime();
+            do { job.work(); runs++; }
+            while ((totalTime = System.nanoTime() - startTime) < warmupNanos);
+            nanoss[i] = totalTime/runs;
         }
         return nanoss;
     }
 
     private static void time(Job ... jobs) throws Throwable {
-
-        long[] warmup = time0(jobs); // Warm up run
+        if (warmupSeconds > 0.0) time0(jobs); // Warm up run
         long[] nanoss = time0(jobs); // Real timing run
         long[] milliss = new long[jobs.length];
         double[] ratios = new double[jobs.length];
@@ -126,12 +151,17 @@
 
     private static int intArg(String[] args, String keyword, int defaultValue) {
         String val = keywordValue(args, keyword);
-        return val == null ? defaultValue : Integer.parseInt(val);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    private static double doubleArg(String[] args, String keyword, double defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Double.parseDouble(val);
     }
 
     private static Pattern patternArg(String[] args, String keyword) {
         String val = keywordValue(args, keyword);
-        return val == null ? null : Pattern.compile(val);
+        return (val == null) ? null : Pattern.compile(val);
     }
 
     private static Job[] filter(Pattern filter, Job[] jobs) {
@@ -166,26 +196,33 @@
                     public void remove()     {        it.remove(); }};}};
     }
 
-    /**
-     * Usage: [iterations=N] [size=N] [filter=REGEXP]
-     */
     public static void main(String[] args) throws Throwable {
-        final int iterations = intArg(args, "iterations", 100000);
+        final int iterations = intArg(args, "iterations", 100_000);
         final int size       = intArg(args, "size", 1000);
+        warmupSeconds        = doubleArg(args, "warmup", 7.0);
         final Pattern filter = patternArg(args, "filter");
 
+        warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L));
+
+//         System.out.printf(
+//             "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
+//             iterations, size, warmupSeconds, filter);
+
         final ConcurrentSkipListMap<Integer,Integer> m
             = new ConcurrentSkipListMap<Integer,Integer>();
-        final Vector<Integer> v = new Vector<Integer>(size);
         final ArrayList<Integer> al = new ArrayList<Integer>(size);
 
         // Populate collections with random data
-        final Random rnd = new Random();
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
         for (int i = 0; i < size; i++) {
             m.put(rnd.nextInt(size), rnd.nextInt(size));
-            v.add(rnd.nextInt(size));
+            al.add(rnd.nextInt(size));
         }
-        al.addAll(v);
+        final Vector<Integer> v = new Vector<Integer>(al);
+        final ArrayDeque<Integer> ad = new ArrayDeque<Integer>(al);
+        // shuffle ArrayDeque elements so they wrap
+        for (int i = 0, n = rnd.nextInt(size); i < n; i++)
+            ad.addLast(ad.removeFirst());
 
         // Also test "short" collections
         final int shortSize = 5;
@@ -222,6 +259,15 @@
                         for (int j = 0; j < size; ++j)
                             sum += a[j];
                         check.sum(sum);}}},
+            new Job("descending array loop") {
+                public void work() throws Throwable {
+                    Integer[] a = al.toArray(new Integer[0]);
+                    for (int i = 0; i < iterations; i++) {
+                        int sum = 0;
+                        int size = a.length;
+                        for (int j = size - 1; j >= 0; j--)
+                            sum += a[j];
+                        check.sum(sum);}}},
             new Job("Vector get loop") {
                 public void work() throws Throwable {
                     for (int i = 0; i < iterations; i++) {
@@ -334,6 +380,13 @@
                         for (Integer n : al)
                             sum += n;
                         check.sum(sum);}}},
+            new Job("ArrayDeque iterate for loop") {
+                public void work() throws Throwable {
+                    for (int i = 0; i < iterations; i++) {
+                        int sum = 0;
+                        for (Integer n : ad)
+                            sum += n;
+                        check.sum(sum);}}},
             new Job("ArrayList descending listIterator loop") {
                 public void work() throws Throwable {
                     for (int i = 0; i < iterations; i++) {
@@ -350,6 +403,137 @@
                         while (it.hasNext())
                             sum += it.next();
                         check.sum(sum);}}},
+            new Job("ArrayDeque.descendingIterator() loop") {
+                public void work() throws Throwable {
+                    for (int i = 0; i < iterations; i++) {
+                        int sum = 0;
+                        Iterator<Integer> it = ad.descendingIterator();
+                        while (it.hasNext())
+                            sum += it.next();
+                        check.sum(sum);}}},
+            new Job("ArrayList.forEach") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        al.forEach(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.forEach") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        ad.forEach(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("Vector.forEach") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        v.forEach(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayList.iterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        al.iterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.descendingIterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        ad.descendingIterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.iterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        ad.iterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("Vector.iterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        v.iterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayList.spliterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        al.spliterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.spliterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        ad.spliterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("Vector.spliterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        v.spliterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job("ArrayList.spliterator().tryAdvance()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        Spliterator<Integer> spliterator = al.spliterator();
+                        do {} while (spliterator.tryAdvance(n -> sum[0] += n));
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.spliterator().tryAdvance()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        Spliterator<Integer> spliterator = ad.spliterator();
+                        do {} while (spliterator.tryAdvance(n -> sum[0] += n));
+                        check.sum(sum[0]);}}},
+            new Job("Vector.spliterator().tryAdvance()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        Spliterator<Integer> spliterator = v.spliterator();
+                        do {} while (spliterator.tryAdvance(n -> sum[0] += n));
+                        check.sum(sum[0]);}}},
+            new Job("ArrayList.removeIf") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        al.removeIf(n -> { sum[0] += n; return false; });
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.removeIf") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        ad.removeIf(n -> { sum[0] += n; return false; });
+                        check.sum(sum[0]);}}},
+            new Job("Vector.removeIf") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        v.removeIf(n -> { sum[0] += n; return false; });
+                        check.sum(sum[0]);}}},
+            new Job("ArrayList subList .removeIf") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    List<Integer> sl = asSubList(al);
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        sl.removeIf(n -> { sum[0] += n; return false; });
+                        check.sum(sum[0]);}}},
             new Job("ArrayList subList get loop") {
                 public void work() throws Throwable {
                     List<Integer> sl = asSubList(al);
@@ -442,7 +626,61 @@
                         int sum = 0;
                         for (Map.Entry<Integer,Integer> e : m.entrySet())
                             sum += e.getKey();
-                        deoptimize(sum);}}}
+                        deoptimize(sum);}}},
+            new Job("ArrayList.toArray()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        for (Object o : al.toArray())
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job("ArrayList.toArray(a)") {
+                public void work() throws Throwable {
+                    Integer[] a = new Integer[size];
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        al.toArray(a);
+                        for (Object o : a)
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.toArray()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        for (Object o : ad.toArray())
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job("ArrayDeque.toArray(a)") {
+                public void work() throws Throwable {
+                    Integer[] a = new Integer[size];
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        ad.toArray(a);
+                        for (Object o : a)
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job("Vector.toArray()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        for (Object o : v.toArray())
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job("Vector.toArray(a)") {
+                public void work() throws Throwable {
+                    Integer[] a = new Integer[size];
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        v.toArray(a);
+                        for (Object o : a)
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
         };
 
         time(filter(filter, jobs));
diff --git a/jdk/test/java/util/Calendar/StampOverflow.java b/jdk/test/java/util/Calendar/StampOverflow.java
index fc10595..f234d4e 100644
--- a/jdk/test/java/util/Calendar/StampOverflow.java
+++ b/jdk/test/java/util/Calendar/StampOverflow.java
@@ -25,6 +25,7 @@
  * @test
  * @bug 4404619 6348819
  * @summary Make sure that Calendar doesn't cause nextStamp overflow.
+ * @modules java.base/java.util:open
  */
 
 import java.lang.reflect.*;
diff --git a/jdk/test/java/util/Collection/CollectionDefaults.java b/jdk/test/java/util/Collection/CollectionDefaults.java
index c2d147f..a920bac 100644
--- a/jdk/test/java/util/Collection/CollectionDefaults.java
+++ b/jdk/test/java/util/Collection/CollectionDefaults.java
@@ -60,9 +60,19 @@
     public static final Predicate<Integer> pEven = x -> 0 == x % 2;
     public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
 
+    private static final int SIZE = 100;
+
     private static final List<Function<Collection<Integer>, Collection<Integer>>> TEST_SUPPLIERS = Arrays.asList(
             // Collection
             ExtendsAbstractCollection<Integer>::new,
+            java.util.ArrayDeque<Integer>::new,
+            java.util.concurrent.ConcurrentLinkedDeque<Integer>::new,
+            java.util.concurrent.ConcurrentLinkedQueue<Integer>::new,
+            java.util.concurrent.LinkedBlockingDeque<Integer>::new,
+            java.util.concurrent.LinkedBlockingQueue<Integer>::new,
+            java.util.concurrent.LinkedTransferQueue<Integer>::new,
+            (coll) -> new java.util.concurrent.ArrayBlockingQueue<Integer>(
+                3 * SIZE, false, coll),
 
             // Lists
             java.util.ArrayList<Integer>::new,
@@ -80,8 +90,6 @@
             ExtendsAbstractSet<Integer>::new
        );
 
-    private static final int SIZE = 100;
-
     @DataProvider(name="setProvider", parallel=true)
     public static Iterator<Object[]> setCases() {
         final List<Object[]> cases = new LinkedList<>();
diff --git a/jdk/test/java/util/Collection/IteratorMicroBenchmark.java b/jdk/test/java/util/Collection/IteratorMicroBenchmark.java
new file mode 100644
index 0000000..263da15
--- /dev/null
+++ b/jdk/test/java/util/Collection/IteratorMicroBenchmark.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 micro-benchmark correctness mode
+ * @run main IteratorMicroBenchmark iterations=1 size=8 warmup=0
+ */
+
+import static java.util.stream.Collectors.summingInt;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.Spliterator;
+import java.util.Vector;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+/**
+ * Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
+ *
+ * To run this in micro-benchmark mode, simply run as a normal java program.
+ * Be patient; this program runs for a very long time.
+ * For faster runs, restrict execution using command line args.
+ *
+ * This is an interface based version of ArrayList/IteratorMicroBenchmark
+ *
+ * @author Martin Buchholz
+ */
+public class IteratorMicroBenchmark {
+    abstract static class Job {
+        private final String name;
+        public Job(String name) { this.name = name; }
+        public String name() { return name; }
+        public abstract void work() throws Throwable;
+    }
+
+    final int iterations;
+    final int size;             // number of elements in collections
+    final double warmupSeconds;
+    final long warmupNanos;
+    final Pattern filter;       // select subset of Jobs to run
+    final boolean reverse;      // reverse order of Jobs
+    final boolean shuffle;      // randomize order of Jobs
+
+    IteratorMicroBenchmark(String[] args) {
+        iterations    = intArg(args, "iterations", 10_000);
+        size          = intArg(args, "size", 1000);
+        warmupSeconds = doubleArg(args, "warmup", 7.0);
+        filter        = patternArg(args, "filter");
+        reverse       = booleanArg(args, "reverse");
+        shuffle       = booleanArg(args, "shuffle");
+
+        warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L));
+    }
+
+    // --------------- GC finalization infrastructure ---------------
+
+    /** No guarantees, but effective in practice. */
+    static void forceFullGc() {
+        CountDownLatch finalizeDone = new CountDownLatch(1);
+        WeakReference<?> ref = new WeakReference<Object>(new Object() {
+            protected void finalize() { finalizeDone.countDown(); }});
+        try {
+            for (int i = 0; i < 10; i++) {
+                System.gc();
+                if (finalizeDone.await(1L, TimeUnit.SECONDS) && ref.get() == null) {
+                    System.runFinalization(); // try to pick up stragglers
+                    return;
+                }
+            }
+        } catch (InterruptedException unexpected) {
+            throw new AssertionError("unexpected InterruptedException");
+        }
+        throw new AssertionError("failed to do a \"full\" gc");
+    }
+
+    /**
+     * Runs each job for long enough that all the runtime compilers
+     * have had plenty of time to warm up, i.e. get around to
+     * compiling everything worth compiling.
+     * Returns array of average times per job per run.
+     */
+    long[] time0(List<Job> jobs) throws Throwable {
+        final int size = jobs.size();
+        long[] nanoss = new long[size];
+        for (int i = 0; i < size; i++) {
+            if (warmupNanos > 0) forceFullGc();
+            Job job = jobs.get(i);
+            long totalTime;
+            int runs = 0;
+            long startTime = System.nanoTime();
+            do { job.work(); runs++; }
+            while ((totalTime = System.nanoTime() - startTime) < warmupNanos);
+            nanoss[i] = totalTime/runs;
+        }
+        return nanoss;
+    }
+
+    void time(List<Job> jobs) throws Throwable {
+        if (warmupNanos > 0) time0(jobs); // Warm up run
+        final int size = jobs.size();
+        final long[] nanoss = time0(jobs); // Real timing run
+        final long[] milliss = new long[size];
+        final double[] ratios = new double[size];
+
+        final String nameHeader   = "Method";
+        final String millisHeader = "Millis";
+        final String ratioHeader  = "Ratio";
+
+        int nameWidth   = nameHeader.length();
+        int millisWidth = millisHeader.length();
+        int ratioWidth  = ratioHeader.length();
+
+        for (int i = 0; i < size; i++) {
+            nameWidth = Math.max(nameWidth, jobs.get(i).name().length());
+
+            milliss[i] = nanoss[i]/(1000L * 1000L);
+            millisWidth = Math.max(millisWidth,
+                                   String.format("%d", milliss[i]).length());
+
+            ratios[i] = (double) nanoss[i] / (double) nanoss[0];
+            ratioWidth = Math.max(ratioWidth,
+                                  String.format("%.3f", ratios[i]).length());
+        }
+
+        String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
+                                      nameWidth, millisWidth, ratioWidth);
+        String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
+                                            nameWidth, millisWidth, ratioWidth);
+        System.out.printf(headerFormat, "Method", "Millis", "Ratio");
+
+        // Print out absolute and relative times, calibrated against first job
+        for (int i = 0; i < size; i++)
+            System.out.printf(format, jobs.get(i).name(), milliss[i], ratios[i]);
+    }
+
+    private static String keywordValue(String[] args, String keyword) {
+        for (String arg : args)
+            if (arg.startsWith(keyword))
+                return arg.substring(keyword.length() + 1);
+        return null;
+    }
+
+    private static int intArg(String[] args, String keyword, int defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    private static double doubleArg(String[] args, String keyword, double defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Double.parseDouble(val);
+    }
+
+    private static Pattern patternArg(String[] args, String keyword) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? null : Pattern.compile(val);
+    }
+
+    private static boolean booleanArg(String[] args, String keyword) {
+        String val = keywordValue(args, keyword);
+        if (val == null || val.equals("false")) return false;
+        if (val.equals("true")) return true;
+        throw new IllegalArgumentException(val);
+    }
+
+    private static List<Job> filter(Pattern filter, List<Job> jobs) {
+        if (filter == null) return jobs;
+        ArrayList<Job> newJobs = new ArrayList<>();
+        for (Job job : jobs)
+            if (filter.matcher(job.name()).find())
+                newJobs.add(job);
+        return newJobs;
+    }
+
+    private static void deoptimize(int sum) {
+        if (sum == 42)
+            System.out.println("the answer");
+    }
+
+    private static <T> List<T> asSubList(List<T> list) {
+        return list.subList(0, list.size());
+    }
+
+    private static <T> Iterable<T> backwards(final List<T> list) {
+        return new Iterable<T>() {
+            public Iterator<T> iterator() {
+                return new Iterator<T>() {
+                    final ListIterator<T> it = list.listIterator(list.size());
+                    public boolean hasNext() { return it.hasPrevious(); }
+                    public T next()          { return it.previous(); }
+                    public void remove()     {        it.remove(); }};}};
+    }
+
+    // Checks for correctness *and* prevents loop optimizations
+    class Check {
+        private int sum;
+        public void sum(int sum) {
+            if (this.sum == 0)
+                this.sum = sum;
+            if (this.sum != sum)
+                throw new AssertionError("Sum mismatch");
+        }
+    }
+    volatile Check check = new Check();
+
+    public static void main(String[] args) throws Throwable {
+        new IteratorMicroBenchmark(args).run();
+    }
+
+    void run() throws Throwable {
+//         System.out.printf(
+//             "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
+//             iterations, size, warmupSeconds, filter);
+
+        final ArrayList<Integer> al = new ArrayList<Integer>(size);
+
+        // Populate collections with random data
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        for (int i = 0; i < size; i++)
+            al.add(rnd.nextInt(size));
+
+        final ArrayDeque<Integer> ad = new ArrayDeque<>(al);
+        final ArrayBlockingQueue<Integer> abq = new ArrayBlockingQueue<>(al.size());
+        abq.addAll(al);
+
+        // shuffle circular array elements so they wrap
+        for (int i = 0, n = rnd.nextInt(size); i < n; i++) {
+            ad.addLast(ad.removeFirst());
+            abq.add(abq.remove());
+        }
+
+        ArrayList<Job> jobs = new ArrayList<>(Arrays.asList());
+
+        List.of(al, ad, abq,
+                new LinkedList<>(al),
+                new PriorityQueue<>(al),
+                new Vector<>(al),
+                new ConcurrentLinkedQueue<>(al),
+                new ConcurrentLinkedDeque<>(al),
+                new LinkedBlockingQueue<>(al),
+                new LinkedBlockingDeque<>(al),
+                new LinkedTransferQueue<>(al),
+                new PriorityBlockingQueue<>(al))
+            .stream()
+            .forEach(x -> {
+                         jobs.addAll(collectionJobs(x));
+                         if (x instanceof Deque)
+                             jobs.addAll(dequeJobs((Deque<Integer>)x));
+                     });
+
+        if (reverse) Collections.reverse(jobs);
+        if (shuffle) Collections.shuffle(jobs);
+
+        time(filter(filter, jobs));
+    }
+
+    List<Job> collectionJobs(Collection<Integer> x) {
+        String klazz = x.getClass().getSimpleName();
+        return List.of(
+            new Job(klazz + " iterate for loop") {
+                public void work() throws Throwable {
+                    for (int i = 0; i < iterations; i++) {
+                        int sum = 0;
+                        for (Integer n : x)
+                            sum += n;
+                        check.sum(sum);}}},
+            new Job(klazz + " .iterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.iterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .spliterator().tryAdvance()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        Spliterator<Integer> spliterator = x.spliterator();
+                        do {} while (spliterator.tryAdvance(n -> sum[0] += n));
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .spliterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.spliterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .removeIf") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.removeIf(n -> { sum[0] += n; return false; });
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .forEach") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.forEach(n -> sum[0] += n);
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .toArray()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        for (Object o : x.toArray())
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .toArray(a)") {
+                public void work() throws Throwable {
+                    Integer[] a = new Integer[x.size()];
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.toArray(a);
+                        for (Object o : a)
+                            sum[0] += (Integer) o;
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .toArray(empty)") {
+                public void work() throws Throwable {
+                    Integer[] empty = new Integer[0];
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        for (Integer o : x.toArray(empty))
+                            sum[0] += o;
+                        check.sum(sum[0]);}}},
+            new Job(klazz + " .stream().collect") {
+                public void work() throws Throwable {
+                    for (int i = 0; i < iterations; i++) {
+                        check.sum(x.stream()
+                                  .collect(summingInt(e -> e)));}}},
+            new Job(klazz + " .parallelStream().collect") {
+                public void work() throws Throwable {
+                    for (int i = 0; i < iterations; i++) {
+                        check.sum(x.parallelStream()
+                                  .collect(summingInt(e -> e)));}}});
+    }
+
+    List<Job> dequeJobs(Deque<Integer> x) {
+        String klazz = x.getClass().getSimpleName();
+        return List.of(
+            new Job(klazz + " .descendingIterator() loop") {
+                public void work() throws Throwable {
+                    for (int i = 0; i < iterations; i++) {
+                        int sum = 0;
+                        Iterator<Integer> it = x.descendingIterator();
+                        while (it.hasNext())
+                            sum += it.next();
+                        check.sum(sum);}}},
+            new Job(klazz + " .descendingIterator().forEachRemaining()") {
+                public void work() throws Throwable {
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.descendingIterator().forEachRemaining(n -> sum[0] += n);
+                        check.sum(sum[0]);}}});
+    }
+}
diff --git a/jdk/test/java/util/Collection/MOAT.java b/jdk/test/java/util/Collection/MOAT.java
index f74a178..b007f69 100644
--- a/jdk/test/java/util/Collection/MOAT.java
+++ b/jdk/test/java/util/Collection/MOAT.java
@@ -29,6 +29,7 @@
  *          4802647 7123424 8024709
  * @summary Run many tests on many Collection and Map implementations
  * @author  Martin Buchholz
+ * @modules java.base/java.util:open
  * @run main MOAT
  * @key randomness
  */
diff --git a/jdk/test/java/util/Collection/RemoveMicroBenchmark.java b/jdk/test/java/util/Collection/RemoveMicroBenchmark.java
new file mode 100644
index 0000000..445baad
--- /dev/null
+++ b/jdk/test/java/util/Collection/RemoveMicroBenchmark.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 micro-benchmark correctness mode
+ * @run main RemoveMicroBenchmark iterations=1 size=8 warmup=0
+ */
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.Spliterator;
+import java.util.Vector;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+import java.util.function.Supplier;
+
+/**
+ * Usage: [iterations=N] [size=N] [filter=REGEXP] [warmup=SECONDS]
+ *
+ * To run this in micro-benchmark mode, simply run as a normal java program.
+ * Be patient; this program runs for a very long time.
+ * For faster runs, restrict execution using command line args.
+ *
+ * @author Martin Buchholz
+ */
+public class RemoveMicroBenchmark {
+    abstract static class Job {
+        private final String name;
+        public Job(String name) { this.name = name; }
+        public String name() { return name; }
+        public abstract void work() throws Throwable;
+    }
+
+    final int iterations;
+    final int size;             // number of elements in collections
+    final double warmupSeconds;
+    final long warmupNanos;
+    final Pattern filter;       // select subset of Jobs to run
+    final boolean reverse;      // reverse order of Jobs
+    final boolean shuffle;      // randomize order of Jobs
+
+    RemoveMicroBenchmark(String[] args) {
+        iterations    = intArg(args, "iterations", 10_000);
+        size          = intArg(args, "size", 1000);
+        warmupSeconds = doubleArg(args, "warmup", 7.0);
+        filter        = patternArg(args, "filter");
+        reverse       = booleanArg(args, "reverse");
+        shuffle       = booleanArg(args, "shuffle");
+
+        warmupNanos = (long) (warmupSeconds * (1000L * 1000L * 1000L));
+    }
+
+    // --------------- GC finalization infrastructure ---------------
+
+    /** No guarantees, but effective in practice. */
+    static void forceFullGc() {
+        CountDownLatch finalizeDone = new CountDownLatch(1);
+        WeakReference<?> ref = new WeakReference<Object>(new Object() {
+            protected void finalize() { finalizeDone.countDown(); }});
+        try {
+            for (int i = 0; i < 10; i++) {
+                System.gc();
+                if (finalizeDone.await(1L, TimeUnit.SECONDS) && ref.get() == null) {
+                    System.runFinalization(); // try to pick up stragglers
+                    return;
+                }
+            }
+        } catch (InterruptedException unexpected) {
+            throw new AssertionError("unexpected InterruptedException");
+        }
+        throw new AssertionError("failed to do a \"full\" gc");
+    }
+
+    /**
+     * Runs each job for long enough that all the runtime compilers
+     * have had plenty of time to warm up, i.e. get around to
+     * compiling everything worth compiling.
+     * Returns array of average times per job per run.
+     */
+    long[] time0(List<Job> jobs) throws Throwable {
+        final int size = jobs.size();
+        long[] nanoss = new long[size];
+        for (int i = 0; i < size; i++) {
+            if (warmupNanos > 0) forceFullGc();
+            Job job = jobs.get(i);
+            long totalTime;
+            int runs = 0;
+            long startTime = System.nanoTime();
+            do { job.work(); runs++; }
+            while ((totalTime = System.nanoTime() - startTime) < warmupNanos);
+            nanoss[i] = totalTime/runs;
+        }
+        return nanoss;
+    }
+
+    void time(List<Job> jobs) throws Throwable {
+        if (warmupNanos > 0) time0(jobs); // Warm up run
+        final int size = jobs.size();
+        final long[] nanoss = time0(jobs); // Real timing run
+        final long[] milliss = new long[size];
+        final double[] ratios = new double[size];
+
+        final String nameHeader   = "Method";
+        final String millisHeader = "Millis";
+        final String ratioHeader  = "Ratio";
+
+        int nameWidth   = nameHeader.length();
+        int millisWidth = millisHeader.length();
+        int ratioWidth  = ratioHeader.length();
+
+        for (int i = 0; i < size; i++) {
+            nameWidth = Math.max(nameWidth, jobs.get(i).name().length());
+
+            milliss[i] = nanoss[i]/(1000L * 1000L);
+            millisWidth = Math.max(millisWidth,
+                                   String.format("%d", milliss[i]).length());
+
+            ratios[i] = (double) nanoss[i] / (double) nanoss[0];
+            ratioWidth = Math.max(ratioWidth,
+                                  String.format("%.3f", ratios[i]).length());
+        }
+
+        String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
+                                      nameWidth, millisWidth, ratioWidth);
+        String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
+                                            nameWidth, millisWidth, ratioWidth);
+        System.out.printf(headerFormat, "Method", "Millis", "Ratio");
+
+        // Print out absolute and relative times, calibrated against first job
+        for (int i = 0; i < size; i++)
+            System.out.printf(format, jobs.get(i).name(), milliss[i], ratios[i]);
+    }
+
+    private static String keywordValue(String[] args, String keyword) {
+        for (String arg : args)
+            if (arg.startsWith(keyword))
+                return arg.substring(keyword.length() + 1);
+        return null;
+    }
+
+    private static int intArg(String[] args, String keyword, int defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Integer.parseInt(val);
+    }
+
+    private static double doubleArg(String[] args, String keyword, double defaultValue) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? defaultValue : Double.parseDouble(val);
+    }
+
+    private static Pattern patternArg(String[] args, String keyword) {
+        String val = keywordValue(args, keyword);
+        return (val == null) ? null : Pattern.compile(val);
+    }
+
+    private static boolean booleanArg(String[] args, String keyword) {
+        String val = keywordValue(args, keyword);
+        if (val == null || val.equals("false")) return false;
+        if (val.equals("true")) return true;
+        throw new IllegalArgumentException(val);
+    }
+
+    private static List<Job> filter(Pattern filter, List<Job> jobs) {
+        if (filter == null) return jobs;
+        ArrayList<Job> newJobs = new ArrayList<>();
+        for (Job job : jobs)
+            if (filter.matcher(job.name()).find())
+                newJobs.add(job);
+        return newJobs;
+    }
+
+    private static void deoptimize(int sum) {
+        if (sum == 42)
+            System.out.println("the answer");
+    }
+
+    private static <T> List<T> asSubList(List<T> list) {
+        return list.subList(0, list.size());
+    }
+
+    private static <T> Iterable<T> backwards(final List<T> list) {
+        return new Iterable<T>() {
+            public Iterator<T> iterator() {
+                return new Iterator<T>() {
+                    final ListIterator<T> it = list.listIterator(list.size());
+                    public boolean hasNext() { return it.hasPrevious(); }
+                    public T next()          { return it.previous(); }
+                    public void remove()     {        it.remove(); }};}};
+    }
+
+    // Checks for correctness *and* prevents loop optimizations
+    class Check {
+        private int sum;
+        public void sum(int sum) {
+            if (this.sum == 0)
+                this.sum = sum;
+            if (this.sum != sum)
+                throw new AssertionError("Sum mismatch");
+        }
+    }
+    volatile Check check = new Check();
+
+    public static void main(String[] args) throws Throwable {
+        new RemoveMicroBenchmark(args).run();
+    }
+
+    void run() throws Throwable {
+//         System.out.printf(
+//             "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
+//             iterations, size, warmupSeconds, filter);
+
+        final ArrayList<Integer> al = new ArrayList<Integer>(size);
+
+        // Populate collections with random data
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        for (int i = 0; i < size; i++)
+            al.add(rnd.nextInt(size));
+
+        ArrayList<Job> jobs = new ArrayList<>();
+
+        List.<Collection<Integer>>of(
+            new ArrayList<>(),
+            new LinkedList<>(),
+            new Vector<>(),
+            new ArrayDeque<>(),
+            new PriorityQueue<>(),
+            new ArrayBlockingQueue<>(al.size()),
+            new ConcurrentLinkedQueue<>(),
+            new ConcurrentLinkedDeque<>(),
+            new LinkedBlockingQueue<>(),
+            new LinkedBlockingDeque<>(),
+            new LinkedTransferQueue<>(),
+            new PriorityBlockingQueue<>())
+            .stream().forEach(
+                x -> {
+                    String klazz = x.getClass().getSimpleName();
+                    jobs.addAll(collectionJobs(klazz, () -> x, al));
+                    if (x instanceof Queue) {
+                        Queue<Integer> queue = (Queue<Integer>) x;
+                        jobs.addAll(queueJobs(klazz, () -> queue, al));
+                    }
+                    if (x instanceof Deque) {
+                        Deque<Integer> deque = (Deque<Integer>) x;
+                        jobs.addAll(dequeJobs(klazz, () -> deque, al));
+                    }
+                    if (x instanceof BlockingQueue) {
+                        BlockingQueue<Integer> q = (BlockingQueue<Integer>) x;
+                        jobs.addAll(blockingQueueJobs(klazz, () -> q, al));
+                    }
+                    if (x instanceof BlockingDeque) {
+                        BlockingDeque<Integer> q = (BlockingDeque<Integer>) x;
+                        jobs.addAll(blockingDequeJobs(klazz, () -> q, al));
+                    }
+                    if (x instanceof List) {
+                        List<Integer> list = (List<Integer>) x;
+                        jobs.addAll(
+                            collectionJobs(
+                                klazz + " subList",
+                                () -> list.subList(0, x.size()),
+                                al));
+                    }
+                });
+
+        if (reverse) Collections.reverse(jobs);
+        if (shuffle) Collections.shuffle(jobs);
+
+        time(filter(filter, jobs));
+    }
+
+    Collection<Integer> universeRecorder(int[] sum) {
+        return new ArrayList<>() {
+            public boolean contains(Object x) {
+                sum[0] += (Integer) x;
+                return true;
+            }};
+    }
+
+    Collection<Integer> emptyRecorder(int[] sum) {
+        return new ArrayList<>() {
+            public boolean contains(Object x) {
+                sum[0] += (Integer) x;
+                return false;
+            }};
+    }
+
+    List<Job> collectionJobs(
+        String description,
+        Supplier<Collection<Integer>> supplier,
+        ArrayList<Integer> al) {
+        return List.of(
+            new Job(description + " .removeIf") {
+                public void work() throws Throwable {
+                    Collection<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        x.removeIf(n -> { sum[0] += n; return true; });
+                        check.sum(sum[0]);}}},
+            new Job(description + " .removeAll") {
+                public void work() throws Throwable {
+                    Collection<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    Collection<Integer> universe = universeRecorder(sum);
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        x.removeAll(universe);
+                        check.sum(sum[0]);}}},
+            new Job(description + " .retainAll") {
+                public void work() throws Throwable {
+                    Collection<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    Collection<Integer> empty = emptyRecorder(sum);
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        x.retainAll(empty);
+                        check.sum(sum[0]);}}},
+            new Job(description + " Iterator.remove") {
+                public void work() throws Throwable {
+                    Collection<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        Iterator<Integer> it = x.iterator();
+                        while (it.hasNext()) {
+                            sum[0] += it.next();
+                            it.remove();
+                        }
+                        check.sum(sum[0]);}}},
+            new Job(description + " clear") {
+                public void work() throws Throwable {
+                    Collection<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        x.forEach(e -> sum[0] += e);
+                        x.clear();
+                        check.sum(sum[0]);}}});
+    }
+
+    List<Job> queueJobs(
+        String description,
+        Supplier<Queue<Integer>> supplier,
+        ArrayList<Integer> al) {
+        return List.of(
+            new Job(description + " poll()") {
+                public void work() throws Throwable {
+                    Queue<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        for (Integer e; (e = x.poll()) != null; )
+                            sum[0] += e;
+                        check.sum(sum[0]);}}});
+    }
+
+    List<Job> dequeJobs(
+        String description,
+        Supplier<Deque<Integer>> supplier,
+        ArrayList<Integer> al) {
+        return List.of(
+            new Job(description + " descendingIterator().remove") {
+                public void work() throws Throwable {
+                    Deque<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        Iterator<Integer> it = x.descendingIterator();
+                        while (it.hasNext()) {
+                            sum[0] += it.next();
+                            it.remove();
+                        }
+                        check.sum(sum[0]);}}},
+            new Job(description + " pollFirst()") {
+                public void work() throws Throwable {
+                    Deque<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        for (Integer e; (e = x.pollFirst()) != null; )
+                            sum[0] += e;
+                        check.sum(sum[0]);}}},
+            new Job(description + " pollLast()") {
+                public void work() throws Throwable {
+                    Deque<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        for (Integer e; (e = x.pollLast()) != null; )
+                            sum[0] += e;
+                        check.sum(sum[0]);}}});
+    }
+
+    List<Job> blockingQueueJobs(
+        String description,
+        Supplier<BlockingQueue<Integer>> supplier,
+        ArrayList<Integer> al) {
+        return List.of(
+            new Job(description + " drainTo(sink)") {
+                public void work() throws Throwable {
+                    BlockingQueue<Integer> x = supplier.get();
+                    ArrayList<Integer> sink = new ArrayList<>();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        sink.clear();
+                        x.addAll(al);
+                        x.drainTo(sink);
+                        sink.forEach(e -> sum[0] += e);
+                        check.sum(sum[0]);}}},
+            new Job(description + " drainTo(sink, n)") {
+                public void work() throws Throwable {
+                    BlockingQueue<Integer> x = supplier.get();
+                    ArrayList<Integer> sink = new ArrayList<>();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        sink.clear();
+                        x.addAll(al);
+                        x.drainTo(sink, al.size());
+                        sink.forEach(e -> sum[0] += e);
+                        check.sum(sum[0]);}}});
+    }
+
+    List<Job> blockingDequeJobs(
+        String description,
+        Supplier<BlockingDeque<Integer>> supplier,
+        ArrayList<Integer> al) {
+        return List.of(
+            new Job(description + " timed pollFirst()") {
+                public void work() throws Throwable {
+                    BlockingDeque<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        for (Integer e; (e = x.pollFirst(0L, TimeUnit.DAYS)) != null; )
+                            sum[0] += e;
+                        check.sum(sum[0]);}}},
+            new Job(description + " timed pollLast()") {
+                public void work() throws Throwable {
+                    BlockingDeque<Integer> x = supplier.get();
+                    int[] sum = new int[1];
+                    for (int i = 0; i < iterations; i++) {
+                        sum[0] = 0;
+                        x.addAll(al);
+                        for (Integer e; (e = x.pollLast(0L, TimeUnit.DAYS)) != null; )
+                            sum[0] += e;
+                        check.sum(sum[0]);}}});
+    }
+}
diff --git a/jdk/test/java/util/Collections/SyncSubMutexes.java b/jdk/test/java/util/Collections/SyncSubMutexes.java
index 05dbcc3..dc2e7e3 100644
--- a/jdk/test/java/util/Collections/SyncSubMutexes.java
+++ b/jdk/test/java/util/Collections/SyncSubMutexes.java
@@ -26,6 +26,7 @@
  * @bug 8048209
  * @summary Check that Collections.synchronizedNavigableSet().tailSet() is using
  * the same lock object as it's source.
+ * @modules java.base/java.util:open
  * @run testng SyncSubMutexes
  */
 import java.lang.reflect.Field;
diff --git a/jdk/test/java/util/Currency/CurrencyTest.java b/jdk/test/java/util/Currency/CurrencyTest.java
index 2a4b6ea..5883939 100644
--- a/jdk/test/java/util/Currency/CurrencyTest.java
+++ b/jdk/test/java/util/Currency/CurrencyTest.java
@@ -25,7 +25,8 @@
  * @bug 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531
  *    6488442 7036905 8008577 8039317 8074350 8074351 8150324
  * @summary Basic tests for Currency class.
- * @modules jdk.localedata
+ * @modules java.base/java.util:open
+ *          jdk.localedata
  */
 
 import java.io.ByteArrayInputStream;
diff --git a/jdk/test/java/util/Currency/ValidateISO4217.java b/jdk/test/java/util/Currency/ValidateISO4217.java
index f482cfd..33cca06 100644
--- a/jdk/test/java/util/Currency/ValidateISO4217.java
+++ b/jdk/test/java/util/Currency/ValidateISO4217.java
@@ -25,6 +25,8 @@
  * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
  *      8039317 8074350 8074351 8145952
  * @summary Validate ISO 4217 data for Currency class.
+ * @modules java.base/java.util:open
+ *          jdk.localedata
  */
 
 /*
diff --git a/jdk/test/java/util/EnumSet/OneUniverse.java b/jdk/test/java/util/EnumSet/OneUniverse.java
index 8ab3de5..d907a7c 100644
--- a/jdk/test/java/util/EnumSet/OneUniverse.java
+++ b/jdk/test/java/util/EnumSet/OneUniverse.java
@@ -25,6 +25,7 @@
  * @test
  * @bug     6276988
  * @summary All enum constants in a class should share a single "universe".
+ * @modules java.base/java.util:open
  */
 
 import java.lang.reflect.Field;
diff --git a/jdk/test/java/util/Hashtable/DeserializedLength.java b/jdk/test/java/util/Hashtable/DeserializedLength.java
index 1497eb8d..376c1f0 100644
--- a/jdk/test/java/util/Hashtable/DeserializedLength.java
+++ b/jdk/test/java/util/Hashtable/DeserializedLength.java
@@ -29,6 +29,7 @@
  * @test
  * @bug 8068427
  * @summary Hashtable deserialization reconstitutes table with wrong capacity
+ * @modules java.base/java.util:open
  */
 public class DeserializedLength {
 
diff --git a/jdk/test/java/util/IdentityHashMap/Capacity.java b/jdk/test/java/util/IdentityHashMap/Capacity.java
index 1be172e..dc75589 100644
--- a/jdk/test/java/util/IdentityHashMap/Capacity.java
+++ b/jdk/test/java/util/IdentityHashMap/Capacity.java
@@ -38,6 +38,7 @@
  * @bug 6904367
  * @summary IdentityHashMap reallocates storage when inserting expected
  *          number of elements
+ * @modules java.base/java.util:open
  * @run testng Capacity
  * @key randomness
  */
diff --git a/jdk/test/java/util/Locale/bug6312358.java b/jdk/test/java/util/Locale/bug6312358.java
index 74a5cd2..ff2ad34 100644
--- a/jdk/test/java/util/Locale/bug6312358.java
+++ b/jdk/test/java/util/Locale/bug6312358.java
@@ -25,6 +25,7 @@
  * @bug 6312358
  * @summary Verify that an NPE is thrown by issueing Locale.getInstance() with
  *      any argument being null.
+ * @modules java.base/java.util:open
  */
 
 import java.lang.reflect.InvocationTargetException;
diff --git a/jdk/test/java/util/ResourceBundle/ReferencesTest.java b/jdk/test/java/util/ResourceBundle/ReferencesTest.java
index 45074d5..7c3a2b2 100644
--- a/jdk/test/java/util/ResourceBundle/ReferencesTest.java
+++ b/jdk/test/java/util/ResourceBundle/ReferencesTest.java
@@ -23,6 +23,7 @@
 /*
  * @test
  * @bug 4405807
+ * @modules java.base/java.util:open
  * @run main/othervm -Xms10m ReferencesTest
  * @summary Verify that references from ResourceBundle cache don't prevent
  * class loader reclamation.
diff --git a/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh b/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh
index e4a5812..bc75ee6 100644
--- a/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh
+++ b/jdk/test/java/util/ResourceBundle/modules/modlocal/modlocal.sh
@@ -71,7 +71,8 @@
 echo 'jdk.test.Main should load bundles local to named module "test".'
 $JAVA -p mods -m test/jdk.test.Main de fr ja zh-tw en de || STATUS=1
 
-echo "jdk.test.Main should NOT load bundles from the jar file specified by the class-path."
-$JAVA -cp extra.jar -p mods -m test/jdk.test.Main vi && STATUS=1
+echo "jdk.test.Main should load bundles from the jar file specified by the class-path."
+$JAVA -cp extra.jar -p mods -m test/jdk.test.Main vi || STATUS=1
+
 
 exit $STATUS
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/Main.java
new file mode 100644
index 0000000..29ef7f1
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/Main.java
@@ -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.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Main {
+    public static void main(String[] args) throws Exception {
+        int errors = 0;
+        for (String loctag : args) {
+            Locale locale = Locale.forLanguageTag(loctag);
+            if (locale.equals(Locale.ROOT)) {
+                continue;
+            }
+            ResourceBundle rb = ResourceBundle.getBundle("jdk.test.resources.MyResources",
+                                                         locale);
+            String tag = locale.toLanguageTag(); // normalized
+            String value = rb.getString("key");
+            System.out.println(rb.getBaseBundleName() + ": locale = " + tag + ", value = " + value);
+            if (!value.startsWith(tag + ':')) {
+                System.out.println("ERROR: " + value + " expected: " + tag);
+                errors++;
+            }
+
+            // inaccessible bundles
+            try {
+                ResourceBundle.getBundle("jdk.test.internal.resources.Foo", locale);
+                System.out.println("ERROR: jdk.test.internal.resources.Foo should not be accessible");
+                errors++;
+            } catch (MissingResourceException e) {
+                e.printStackTrace();
+
+                Throwable cause = e.getCause();
+                System.out.println("Expected: " +
+                    (cause != null ? cause.getMessage() : e.getMessage()));
+            }
+        }
+        if (errors > 0) {
+            throw new RuntimeException(errors + " errors");
+        }
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo.java
similarity index 80%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo.java
index 789cdb9..0f82e89 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.internal.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class Foo extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_de.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_de.java
index 789cdb9..f45e667 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_de.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.internal.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class Foo_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_en.java
similarity index 80%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_en.java
index 789cdb9..78109a7 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_en.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.internal.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class Foo_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_fr.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_fr.java
index 789cdb9..8c2bbd9 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_fr.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.internal.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class Foo_fr extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "fr: message" }
+        };
     }
 }
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_ja.properties b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_ja.properties
new file mode 100644
index 0000000..1979245
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_zh.properties b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_zh.properties
new file mode 100644
index 0000000..c15ed5b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_zh_TW.properties
new file mode 100644
index 0000000..245da34
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/internal/resources/Foo_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources.java
similarity index 80%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources.java
index 789cdb9..8947749 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class MyResources extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "root: message" }
+        };
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_de.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_de.java
index 789cdb9..1b36656 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_de.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class MyResources_de extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "de: message" }
+        };
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_en.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_en.java
index 789cdb9..672dafe 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_en.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class MyResources_en extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "en: message" }
+        };
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_fr.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_fr.java
index 789cdb9..5d7181e 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_fr.java
@@ -21,13 +21,15 @@
  * questions.
  */
 
-package p7;
+package jdk.test.resources;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.util.ListResourceBundle;
+
+public class MyResources_fr extends ListResourceBundle {
+    @Override
+    public Object[][] getContents() {
+        return new Object[][] {
+            { "key", "fr: message" }
+        };
     }
 }
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_ja.properties b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_ja.properties
new file mode 100644
index 0000000..1979245
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_ja.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=ja: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_zh.properties b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_zh.properties
new file mode 100644
index 0000000..c15ed5b
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_zh.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh: message
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_zh_TW.properties b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_zh_TW.properties
new file mode 100644
index 0000000..245da34
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/jdk/test/resources/MyResources_zh_TW.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+key=zh-TW: message
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/module-info.java
index 9d2c8be..bc7232f 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/src/bundles/module-info.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+module bundles {
+    opens jdk.test.resources;
 }
diff --git a/jdk/test/java/util/ResourceBundle/modules/unnamed/unnamed.sh b/jdk/test/java/util/ResourceBundle/modules/unnamed/unnamed.sh
new file mode 100644
index 0000000..1860589
--- /dev/null
+++ b/jdk/test/java/util/ResourceBundle/modules/unnamed/unnamed.sh
@@ -0,0 +1,74 @@
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @summary Test unnamed module to find resource bundles exported
+#          from a named module 
+
+
+set -e
+
+if [ -z "$TESTJAVA" ]; then
+  if [ $# -lt 1 ]; then exit 1; fi
+  TESTJAVA="$1"; shift
+  COMPILEJAVA="${TESTJAVA}"
+  TESTSRC="`pwd`"
+  TESTCLASSES="`pwd`"
+fi
+
+JAVAC="$COMPILEJAVA/bin/javac"
+JAVA="$TESTJAVA/bin/java"
+
+rm -rf mods
+
+mkdir -p mods/test
+
+B=bundles
+mkdir -p mods/$B
+CLASSES="`find $TESTSRC/src/$B -name '*.java'`"
+if [ "x$CLASSES" != x ]; then
+    $JAVAC -g -d mods --module-source-path $TESTSRC/src $CLASSES
+fi
+PROPS="`(cd $TESTSRC/src/$B; find . -name '*.properties')`"
+if [ "x$PROPS" != x ]; then
+    for P in $PROPS
+    do
+      D=`dirname $P`
+      mkdir -p mods/$B/$D
+      cp $TESTSRC/src/$B/$P mods/$B/$D/
+    done
+fi
+
+mkdir classes
+$JAVAC -d classes $TESTSRC/Main.java
+
+# access resource bundles that are exported private unconditionally
+$JAVA -cp classes --module-path mods --add-modules bundles \
+      Main de fr ja zh-tw en de
+
+# --add-exports can't open resources 
+$JAVA -cp classes --module-path mods --add-modules bundles \
+      --add-opens bundles/jdk.test.internal.resources=ALL-UNNAMED \
+      Main de fr ja zh-tw en de
+
+exit $?
diff --git a/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh b/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh
index c37949e..7aeaf82 100644
--- a/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh
+++ b/jdk/test/java/util/ResourceBundle/modules/visibility/visibility.sh
@@ -111,9 +111,9 @@
 runJava -cp mods/named.bundles -p mods -m test/jdk.test.TestWithNoModuleArg \
     jdk.test.resources.props.MyResources true
 runJava -cp mods/named.bundles -p mods -m embargo/jdk.embargo.TestWithNoModuleArg \
-    jdk.test.resources.classes.MyResources false
+    jdk.test.resources.classes.MyResources true
 runJava -cp mods/named.bundles -p mods -m embargo/jdk.embargo.TestWithNoModuleArg \
-    jdk.test.resources.props.MyResources false
+    jdk.test.resources.props.MyResources true
 
 # Tests using jdk.test.TestWithUnnamedModuleArg and jdk.embargo.TestWithUnnamedModuleArg
 # both of which specify an unnamed module with ResourceBundle.getBundle.
@@ -171,13 +171,13 @@
 
 # Add mods/exported.named.bundles to the class path.
 runJava -cp mods/exported.named.bundles -p mods -m test/jdk.test.TestWithNoModuleArg \
-    jdk.test.resources.exported.classes.MyResources false
+    jdk.test.resources.exported.classes.MyResources true
 runJava -cp mods/exported.named.bundles -p mods -m test/jdk.test.TestWithNoModuleArg \
-    jdk.test.resources.exported.props.MyResources false
+    jdk.test.resources.exported.props.MyResources true
 runJava -cp mods/exported.named.bundles -p mods -m embargo/jdk.embargo.TestWithNoModuleArg \
-    jdk.test.resources.exported.classes.MyResources false
+    jdk.test.resources.exported.classes.MyResources true
 runJava -cp mods/exported.named.bundles -p mods -m embargo/jdk.embargo.TestWithNoModuleArg \
-    jdk.test.resources.exported.props.MyResources false
+    jdk.test.resources.exported.props.MyResources true
 
 # Tests using jdk.test.TestWithUnnamedModuleArg and jdk.embargo.TestWithUnnamedModuleArg
 # which specify an unnamed module with ResourceBundle.getBundle.
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/basic/BarProvider.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/basic/BarProvider.java
index 9d2c8be..912172b 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/basic/BarProvider.java
@@ -21,7 +21,4 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+public class BarProvider { }
diff --git a/jdk/test/java/util/ServiceLoader/Basic.java b/jdk/test/java/util/ServiceLoader/basic/Basic.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/Basic.java
rename to jdk/test/java/util/ServiceLoader/basic/Basic.java
diff --git a/jdk/test/java/util/ServiceLoader/FooProvider1.java b/jdk/test/java/util/ServiceLoader/basic/FooProvider1.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/FooProvider1.java
rename to jdk/test/java/util/ServiceLoader/basic/FooProvider1.java
diff --git a/jdk/test/java/util/ServiceLoader/FooProvider2.java b/jdk/test/java/util/ServiceLoader/basic/FooProvider2.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/FooProvider2.java
rename to jdk/test/java/util/ServiceLoader/basic/FooProvider2.java
diff --git a/jdk/test/java/util/ServiceLoader/FooProvider3.java b/jdk/test/java/util/ServiceLoader/basic/FooProvider3.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/FooProvider3.java
rename to jdk/test/java/util/ServiceLoader/basic/FooProvider3.java
diff --git a/jdk/test/java/util/ServiceLoader/FooService.java b/jdk/test/java/util/ServiceLoader/basic/FooService.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/FooService.java
rename to jdk/test/java/util/ServiceLoader/basic/FooService.java
diff --git a/jdk/test/java/util/ServiceLoader/Load.java b/jdk/test/java/util/ServiceLoader/basic/Load.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/Load.java
rename to jdk/test/java/util/ServiceLoader/basic/Load.java
diff --git a/jdk/test/java/util/ServiceLoader/basic.sh b/jdk/test/java/util/ServiceLoader/basic/basic.sh
similarity index 97%
rename from jdk/test/java/util/ServiceLoader/basic.sh
rename to jdk/test/java/util/ServiceLoader/basic/basic.sh
index 3976e0d..4ffd56a 100644
--- a/jdk/test/java/util/ServiceLoader/basic.sh
+++ b/jdk/test/java/util/ServiceLoader/basic/basic.sh
@@ -25,7 +25,7 @@
 # @bug 4640520 6354623 7198496
 # @summary Unit test for java.util.ServiceLoader
 #
-# @build Basic Load FooService FooProvider1 FooProvider2 FooProvider3
+# @build Basic Load FooService FooProvider1 FooProvider2 FooProvider3 BarProvider
 # @run shell basic.sh
 
 # Command-line usage: sh basic.sh /path/to/build
@@ -131,7 +131,7 @@
 mkdir -p x.meta/META-INF/services
 
 # Simple failures
-for p in FooProvider42 'blah blah' 9234 'X!' java.lang.Object; do
+for p in FooProvider42 'blah blah' 9234 'X!' BarProvider; do
   echo $p >x.meta/META-INF/services/FooService
   go ".${SEP}x.meta" "" fail
 done
diff --git a/jdk/test/java/util/ServiceLoader/modules/BadProvidersTest.java b/jdk/test/java/util/ServiceLoader/modules/BadProvidersTest.java
new file mode 100644
index 0000000..c28e3b9
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/BadProvidersTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build CompilerUtils
+ * @run testng/othervm BadProvidersTest
+ * @summary Basic test of ServiceLoader with bad provider and bad provider
+ *          factories deployed on the module path
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.List;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.*;
+
+/**
+ * Basic test of `provides S with PF` and `provides S with P` where the provider
+ * factory or provider
+ */
+
+public class BadProvidersTest {
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path USER_DIR   = Paths.get(System.getProperty("user.dir"));
+    private static final Path SRC_DIR    = Paths.get(TEST_SRC, "modules");
+
+    private static final Path BADFACTORIES_DIR = Paths.get(TEST_SRC, "badfactories");
+    private static final Path BADPROVIDERS_DIR = Paths.get(TEST_SRC, "badproviders");
+
+    private static final String TEST1_MODULE = "test1";
+    private static final String TEST2_MODULE = "test2";
+
+    private static final String TEST_SERVICE = "p.Service";
+
+    /**
+     * Compiles a module, returning a module path with the compiled module.
+     */
+    private Path compileTest(String moduleName) throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path output = Files.createDirectory(dir.resolve(moduleName));
+        boolean compiled = CompilerUtils.compile(SRC_DIR.resolve(moduleName), output);
+        assertTrue(compiled);
+        return dir;
+    }
+
+    /**
+     * Resolves a test module and loads it into its own layer. ServiceLoader
+     * is then used to load all providers.
+     */
+    private List<Provider> loadProviders(Path mp, String moduleName) throws Exception {
+        ModuleFinder finder = ModuleFinder.of(mp);
+
+        Layer bootLayer = Layer.boot();
+
+        Configuration cf = bootLayer.configuration()
+                .resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of(moduleName));
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
+
+        Class<?> service = layer.findLoader(moduleName).loadClass(TEST_SERVICE);
+
+        return ServiceLoader.load(layer, service)
+                .stream()
+                .collect(Collectors.toList());
+    }
+
+    @Test
+    public void sanityTest1() throws Exception {
+        Path mods = compileTest(TEST1_MODULE);
+        List<Provider> list = loadProviders(mods, TEST1_MODULE);
+        assertTrue(list.size() == 1);
+
+        // the provider is a singleton, enforced by the provider factory
+        Object p1 = list.get(0).get();
+        Object p2 = list.get(0).get();
+        assertTrue(p1 != null);
+        assertTrue(p1 == p2);
+    }
+
+    @Test
+    public void sanityTest2() throws Exception {
+        Path mods = compileTest(TEST2_MODULE);
+        List<Provider> list = loadProviders(mods, TEST2_MODULE);
+        assertTrue(list.size() == 1);
+        Object p = list.get(0).get();
+        assertTrue(p != null);
+    }
+
+
+    @DataProvider(name = "badfactories")
+    public Object[][] createBadFactories() {
+        return new Object[][] {
+                { "classnotpublic",     null },
+                { "methodnotpublic",    null },
+                { "badreturntype",      null },
+                { "returnsnull",        null },
+                { "throwsexception",    null },
+        };
+    }
+
+
+    @Test(dataProvider = "badfactories",
+          expectedExceptions = ServiceConfigurationError.class)
+    public void testBadFactory(String testName, String ignore) throws Exception {
+        Path mods = compileTest(TEST1_MODULE);
+
+        // compile the bad factory
+        Path source = BADFACTORIES_DIR.resolve(testName);
+        Path output = Files.createTempDirectory(USER_DIR, "tmp");
+        boolean compiled = CompilerUtils.compile(source, output);
+        assertTrue(compiled);
+
+        // copy the compiled class into the module
+        Path classFile = Paths.get("p", "ProviderFactory.class");
+        Files.copy(output.resolve(classFile),
+                   mods.resolve(TEST1_MODULE).resolve(classFile),
+                   StandardCopyOption.REPLACE_EXISTING);
+
+        // load providers and instantiate each one
+        loadProviders(mods, TEST1_MODULE).forEach(Provider::get);
+    }
+
+
+    @DataProvider(name = "badproviders")
+    public Object[][] createBadProviders() {
+        return new Object[][] {
+                { "notpublic",          null },
+                { "ctornotpublic",      null },
+                { "notasubtype",        null },
+                { "throwsexception",    null }
+        };
+    }
+
+
+    @Test(dataProvider = "badproviders",
+          expectedExceptions = ServiceConfigurationError.class)
+    public void testBadProvider(String testName, String ignore) throws Exception {
+        Path mods = compileTest(TEST2_MODULE);
+
+        // compile the bad provider
+        Path source = BADPROVIDERS_DIR.resolve(testName);
+        Path output = Files.createTempDirectory(USER_DIR, "tmp");
+        boolean compiled = CompilerUtils.compile(source, output);
+        assertTrue(compiled);
+
+        // copy the compiled class into the module
+        Path classFile = Paths.get("p", "Provider.class");
+        Files.copy(output.resolve(classFile),
+                   mods.resolve(TEST2_MODULE).resolve(classFile),
+                   StandardCopyOption.REPLACE_EXISTING);
+
+        // load providers and instantiate each one
+        loadProviders(mods, TEST2_MODULE).forEach(Provider::get);
+    }
+
+}
+
diff --git a/jdk/test/java/util/ServiceLoader/modules/Basic.java b/jdk/test/java/util/ServiceLoader/modules/Basic.java
new file mode 100644
index 0000000..7833c0e
--- /dev/null
+++ b/jdk/test/java/util/ServiceLoader/modules/Basic.java
@@ -0,0 +1,432 @@
+/*
+ * 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
+ * @library modules
+ * @build bananascript/*
+ * @compile src/pearscript/org/pear/PearScriptEngineFactory.java
+ *          src/pearscript/org/pear/PearScript.java
+ * @run testng/othervm Basic
+ * @summary Basic test for ServiceLoader with a provider deployed as a module.
+ */
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.*;
+import java.util.ServiceLoader.Provider;
+import java.util.stream.Collectors;
+import javax.script.ScriptEngineFactory;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeTest;
+import static org.testng.Assert.*;
+
+/**
+ * Basic test for ServiceLoader. The test make use of two service providers:
+ * 1. BananaScriptEngine - a ScriptEngineFactory deployed as a module on the
+ *    module path. It implementations a singleton via the public static
+ *    provider method.
+ * 2. PearScriptEngine - a ScriptEngineFactory deployed on the class path
+ *    with a service configuration file.
+ */
+
+public class Basic {
+
+    // Copy the services configuration file for "pearscript" into place.
+    @BeforeTest
+    public void setup() throws Exception {
+        Path src = Paths.get(System.getProperty("test.src", ""));
+        Path classes = Paths.get(System.getProperty("test.classes", ""));
+        String st = ScriptEngineFactory.class.getName();
+        Path config = Paths.get("META-INF", "services", st);
+        Path source = src.resolve("src").resolve("pearscript").resolve(config);
+        Path target = classes.resolve(config);
+        Files.createDirectories(target.getParent());
+        Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    /**
+     * Basic test of iterator() to ensure that providers located as modules
+     * and on the class path are found.
+     */
+    @Test
+    public void testIterator() {
+        ServiceLoader<ScriptEngineFactory> loader
+            = ServiceLoader.load(ScriptEngineFactory.class);
+        Set<String> names = collectAll(loader)
+                .stream()
+                .map(ScriptEngineFactory::getEngineName)
+                .collect(Collectors.toSet());
+        assertTrue(names.contains("BananaScriptEngine"));
+        assertTrue(names.contains("PearScriptEngine"));
+    }
+
+    /**
+     * Basic test of iterator() to test iteration order. Providers deployed
+     * as named modules should be found before providers deployed on the class
+     * path.
+     */
+    @Test
+    public void testIteratorOrder() {
+        ServiceLoader<ScriptEngineFactory> loader
+            = ServiceLoader.load(ScriptEngineFactory.class);
+        boolean foundUnnamed = false;
+        for (ScriptEngineFactory factory : collectAll(loader)) {
+            if (factory.getClass().getModule().isNamed()) {
+                if (foundUnnamed) {
+                    assertTrue(false, "Named module element after unnamed");
+                }
+            } else {
+                foundUnnamed = true;
+            }
+        }
+    }
+
+    /**
+     * Basic test of Provider::type
+     */
+    @Test
+    public void testProviderType() {
+        Set<String> types = ServiceLoader.load(ScriptEngineFactory.class)
+                .stream()
+                .map(Provider::type)
+                .map(Class::getName)
+                .collect(Collectors.toSet());
+        assertTrue(types.contains("org.banana.BananaScriptEngineFactory"));
+        assertTrue(types.contains("org.pear.PearScriptEngineFactory"));
+    }
+
+    /**
+     * Basic test of Provider::get
+     */
+    @Test
+    public void testProviderGet() {
+        Set<String> names = ServiceLoader.load(ScriptEngineFactory.class)
+                .stream()
+                .map(Provider::get)
+                .map(ScriptEngineFactory::getEngineName)
+                .collect(Collectors.toSet());
+        assertTrue(names.contains("BananaScriptEngine"));
+        assertTrue(names.contains("PearScriptEngine"));
+    }
+
+    /**
+     * Basic test of the public static provider method. BananaScriptEngine
+     * defines a provider method that returns the same instance.
+     */
+    @Test
+    public void testSingleton() {
+        Optional<Provider<ScriptEngineFactory>> oprovider
+            = ServiceLoader.load(ScriptEngineFactory.class)
+                .stream()
+                .filter(p -> p.type().getName().equals("org.banana.BananaScriptEngineFactory"))
+                .findFirst();
+        assertTrue(oprovider.isPresent());
+        Provider<ScriptEngineFactory> provider = oprovider.get();
+
+        // invoke Provider::get twice
+        ScriptEngineFactory factory1 = provider.get();
+        ScriptEngineFactory factory2 = provider.get();
+        assertTrue(factory1 == factory2);
+    }
+
+    /**
+     * Basic test of stream() to ensure that elements for providers in named
+     * modules come before elements for providers in unnamed modules.
+     */
+    @Test
+    public void testStreamOrder() {
+        List<Class<?>> types = ServiceLoader.load(ScriptEngineFactory.class)
+                .stream()
+                .map(Provider::type)
+                .collect(Collectors.toList());
+
+        boolean foundUnnamed = false;
+        for (Class<?> factoryClass : types) {
+            if (factoryClass.getModule().isNamed()) {
+                if (foundUnnamed) {
+                    assertTrue(false, "Named module element after unnamed");
+                }
+            } else {
+                foundUnnamed = true;
+            }
+        }
+    }
+
+    /**
+     * Basic test of ServiceLoader.findFirst()
+     */
+    @Test
+    public void testFindFirst() {
+        Optional<ScriptEngineFactory> ofactory
+            = ServiceLoader.load(ScriptEngineFactory.class).findFirst();
+        assertTrue(ofactory.isPresent());
+        ScriptEngineFactory factory = ofactory.get();
+        assertTrue(factory.getClass().getModule().isNamed());
+
+        class S { }
+        assertFalse(ServiceLoader.load(S.class).findFirst().isPresent());
+    }
+
+    /**
+     * Basic test ServiceLoader.load specifying the platform class loader.
+     * The providers on the module path and class path should not be located.
+     */
+    @Test
+    public void testWithPlatformClassLoader() {
+        ClassLoader pcl = ClassLoader.getPlatformClassLoader();
+
+        // iterator
+        ServiceLoader<ScriptEngineFactory> loader
+                = ServiceLoader.load(ScriptEngineFactory.class, pcl);
+        Set<String> names = collectAll(loader)
+                .stream()
+                .map(ScriptEngineFactory::getEngineName)
+                .collect(Collectors.toSet());
+        assertFalse(names.contains("BananaScriptEngine"));
+        assertFalse(names.contains("PearScriptEngine"));
+
+        // stream
+        names = ServiceLoader.load(ScriptEngineFactory.class, pcl)
+                .stream()
+                .map(Provider::get)
+                .map(ScriptEngineFactory::getEngineName)
+                .collect(Collectors.toSet());
+        assertFalse(names.contains("BananaScriptEngine"));
+        assertFalse(names.contains("PearScriptEngine"));
+    }
+
+    /**
+     * Basic test of ServiceLoader.load, using the class loader for
+     * a module in a custom layer as the context.
+     */
+    @Test
+    public void testWithCustomLayer1() {
+        Layer layer = createCustomLayer("bananascript");
+
+        ClassLoader loader = layer.findLoader("bananascript");
+        List<ScriptEngineFactory> providers
+            = collectAll(ServiceLoader.load(ScriptEngineFactory.class, loader));
+
+        // should have at least 2 x bananascript + pearscript
+        assertTrue(providers.size() >= 3);
+
+        // first element should be the provider in the custom layer
+        ScriptEngineFactory factory = providers.get(0);
+        assertTrue(factory.getClass().getClassLoader() == loader);
+        assertTrue(factory.getClass().getModule().getLayer() == layer);
+        assertTrue(factory.getEngineName().equals("BananaScriptEngine"));
+
+        // remainder should be the boot layer
+        providers.remove(0);
+        Set<String> names = providers.stream()
+                .map(ScriptEngineFactory::getEngineName)
+                .collect(Collectors.toSet());
+        assertTrue(names.contains("BananaScriptEngine"));
+        assertTrue(names.contains("PearScriptEngine"));
+    }
+
+    /**
+     * Basic test of ServiceLoader.load using a custom Layer as the context.
+     */
+    @Test
+    public void testWithCustomLayer2() {
+        Layer layer = createCustomLayer("bananascript");
+
+        List<ScriptEngineFactory> factories
+            = collectAll(ServiceLoader.load(layer, ScriptEngineFactory.class));
+
+        // should have at least 2 x bananascript
+        assertTrue(factories.size() >= 2);
+
+        // first element should be the provider in the custom layer
+        ScriptEngineFactory factory = factories.get(0);
+        assertTrue(factory.getClass().getModule().getLayer() == layer);
+        assertTrue(factory.getEngineName().equals("BananaScriptEngine"));
+
+        // remainder should be the boot layer
+        factories.remove(0);
+        Set<String> names = factories.stream()
+                .map(ScriptEngineFactory::getEngineName)
+                .collect(Collectors.toSet());
+        assertTrue(names.contains("BananaScriptEngine"));
+        assertFalse(names.contains("PearScriptEngine"));
+    }
+
+    /**
+     * Basic test of ServiceLoader.load with a tree of layers.
+     *
+     * Test scenario:
+     * - boot layer contains "bananascript", maybe other script engines
+     * - layer1, with boot layer as parent, contains "bananascript"
+     * - layer2, with boot layer as parent, contains "bananascript"
+     * - layer3, with layer1 ad layer as parents, contains "bananascript"
+     *
+     * ServiceLoader should locate all 4 script engine factories in DFS order.
+     */
+    @Test
+    public void testWithCustomLayer3() {
+        Layer bootLayer = Layer.boot();
+        Configuration cf0 = bootLayer.configuration();
+
+        // boot layer should contain "bananascript"
+        List<ScriptEngineFactory> factories
+            = collectAll(ServiceLoader.load(bootLayer, ScriptEngineFactory.class));
+        int countInBootLayer = factories.size();
+        assertTrue(countInBootLayer >= 1);
+        assertTrue(factories.stream()
+                .map(p -> p.getEngineName())
+                .filter("BananaScriptEngine"::equals)
+                .findAny()
+                .isPresent());
+
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Path dir = Paths.get(System.getProperty("test.classes", "."), "modules");
+        ModuleFinder finder = ModuleFinder.of(dir);
+
+        // layer1
+        Configuration cf1 = cf0.resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of());
+        Layer layer1 = bootLayer.defineModulesWithOneLoader(cf1, scl);
+        assertTrue(layer1.modules().size() == 1);
+
+        // layer2
+        Configuration cf2 = cf0.resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of());
+        Layer layer2 = bootLayer.defineModulesWithOneLoader(cf2, scl);
+        assertTrue(layer2.modules().size() == 1);
+
+        // layer3 with layer1 and layer2 as parents
+        Configuration cf3 = Configuration.resolveRequiresAndUses(finder,
+                List.of(cf1, cf2),
+                ModuleFinder.of(),
+                Set.of());
+        Layer layer3 = Layer.defineModulesWithOneLoader(cf3, List.of(layer1, layer2), scl).layer();
+        assertTrue(layer3.modules().size() == 1);
+
+
+        // class loaders
+        ClassLoader loader1 = layer1.findLoader("bananascript");
+        ClassLoader loader2 = layer2.findLoader("bananascript");
+        ClassLoader loader3 = layer3.findLoader("bananascript");
+        assertTrue(loader1 != loader2);
+        assertTrue(loader1 != loader3);
+        assertTrue(loader2 != loader3);
+
+        // load all factories with layer3 as the context
+        factories = collectAll(ServiceLoader.load(layer3, ScriptEngineFactory.class));
+        int count = factories.size();
+        assertTrue(count == countInBootLayer + 3);
+
+        // the ordering should be layer3, layer1, boot layer, layer2
+
+        ScriptEngineFactory factory = factories.get(0);
+        assertTrue(factory.getClass().getModule().getLayer() == layer3);
+        assertTrue(factory.getClass().getClassLoader() == loader3);
+        assertTrue(factory.getEngineName().equals("BananaScriptEngine"));
+
+        factory = factories.get(1);
+        assertTrue(factory.getClass().getModule().getLayer() == layer1);
+        assertTrue(factory.getClass().getClassLoader() == loader1);
+        assertTrue(factory.getEngineName().equals("BananaScriptEngine"));
+
+        // boot layer "bananascript" and maybe other factories
+        int last = count -1;
+        boolean found = false;
+        for (int i=2; i<last; i++) {
+            factory = factories.get(i);
+            assertTrue(factory.getClass().getModule().getLayer() == bootLayer);
+            if (factory.getEngineName().equals("BananaScriptEngine")) {
+                assertFalse(found);
+                found = true;
+            }
+        }
+        assertTrue(found);
+
+        factory = factories.get(last);
+        assertTrue(factory.getClass().getModule().getLayer() == layer2);
+        assertTrue(factory.getClass().getClassLoader() == loader2);
+        assertTrue(factory.getEngineName().equals("BananaScriptEngine"));
+    }
+
+
+    // -- nulls --
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testLoadNull1() {
+        ServiceLoader.load(null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testLoadNull2() {
+        ServiceLoader.load((Class<?>) null, ClassLoader.getSystemClassLoader());
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testLoadNull3() {
+        class S { }
+        ServiceLoader.load((Layer) null, S.class);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testLoadNull4() {
+        ServiceLoader.load(Layer.empty(), null);
+    }
+
+    @Test(expectedExceptions = { NullPointerException.class })
+    public void testLoadNull5() {
+        ServiceLoader.loadInstalled(null);
+    }
+
+    /**
+     * Create a custom Layer by resolving the given module names. The modules
+     * are located in the {@code ${test.classes}/modules} directory.
+     */
+    private Layer createCustomLayer(String... modules) {
+        Path dir = Paths.get(System.getProperty("test.classes", "."), "modules");
+        ModuleFinder finder = ModuleFinder.of(dir);
+        Set<String> roots = new HashSet<>();
+        Collections.addAll(roots, modules);
+        Layer bootLayer = Layer.boot();
+        Configuration parent = bootLayer.configuration();
+        Configuration cf = parent.resolveRequires(finder, ModuleFinder.of(), roots);
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+        Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
+        assertTrue(layer.modules().size() == 1);
+        return layer;
+    }
+
+    private <E> List<E> collectAll(ServiceLoader<E> loader) {
+        List<E> list = new ArrayList<>();
+        Iterator<E> iterator = loader.iterator();
+        while (iterator.hasNext()) {
+            list.add(iterator.next());
+        }
+        return list;
+    }
+}
+
diff --git a/jdk/test/java/util/ServiceLoader/modules/MiscTests.java b/jdk/test/java/util/ServiceLoader/modules/MiscTests.java
deleted file mode 100644
index 5a99a30..0000000
--- a/jdk/test/java/util/ServiceLoader/modules/MiscTests.java
+++ /dev/null
@@ -1,56 +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.
- */
-
-import java.lang.reflect.Layer;
-import java.security.Provider;
-import java.util.ServiceLoader;
-
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
-/*
- * @test
- * @run testng MiscTests
- * @summary Basic test of ServiceLoader with modules
- */
-
-public class MiscTests {
-
-    @Test
-    public void testEmptyLayer() {
-        ServiceLoader<Provider> sl
-            = ServiceLoader.load(Layer.empty(), Provider.class);
-        assertFalse(sl.iterator().hasNext());
-    }
-
-    @Test(expectedExceptions = { NullPointerException.class })
-    public void testNullLayer() {
-        ServiceLoader.load(null, Provider.class);
-    }
-
-    @Test(expectedExceptions = { NullPointerException.class })
-    public void testNullService() {
-        ServiceLoader.load(Layer.empty(), null);
-    }
-
-}
diff --git a/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java b/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java
deleted file mode 100644
index ff6d1bc..0000000
--- a/jdk/test/java/util/ServiceLoader/modules/ServicesTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.File;
-import java.lang.module.Configuration;
-import java.lang.module.ModuleFinder;
-import java.lang.reflect.Layer;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ServiceLoader;
-import java.util.Set;
-import javax.script.ScriptEngineFactory;
-
-import static jdk.testlibrary.ProcessTools.executeTestJava;
-
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
-/**
- * @test
- * @library /lib/testlibrary
- * @modules java.scripting
- *          jdk.compiler
- * @build ServicesTest CompilerUtils jdk.testlibrary.*
- * @run testng ServicesTest
- * @summary Tests ServiceLoader to locate service providers on the module path
- *          and class path. Also tests ServiceLoader with a custom Layer.
- */
-
-@Test
-public class ServicesTest {
-
-    private static final String TEST_SRC = System.getProperty("test.src");
-
-    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
-    private static final Path CLASSES_DIR = Paths.get("classes");
-    private static final Path MODS_DIR = Paths.get("mods");
-
-    // modules to compile to the module path
-    private static final String MODULES[] = { "test", "bananascript" };
-
-    // directories of classes to compile to the class path
-    private static final String CLASSES[] = { "pearscript" };
-
-    // resources to copy to the class path
-    private static final String RESOURCES[] = {
-        "pearscript/META-INF/services/javax.script.ScriptEngineFactory"
-    };
-
-
-    /**
-     * Compiles all modules and classes used by the test
-     */
-    @BeforeTest
-    public void setup() throws Exception {
-
-        // modules
-        for (String mn : MODULES ) {
-            Path src = SRC_DIR.resolve(mn);
-            Path mods = MODS_DIR.resolve(mn);
-            assertTrue(CompilerUtils.compile(src, mods));
-        }
-
-        // classes
-        for (String dir : CLASSES) {
-            Path src = SRC_DIR.resolve(dir);
-            assertTrue(CompilerUtils.compile(src, CLASSES_DIR));
-        }
-
-        // copy resources
-        for (String rn : RESOURCES) {
-            Path file = Paths.get(rn.replace('/', File.separatorChar));
-            Path source = SRC_DIR.resolve(file);
-
-            // drop directory to get a target of classes/META-INF/...
-            Path target = CLASSES_DIR.resolve(file.subpath(1, file.getNameCount()));
-
-            Files.createDirectories(target.getParent());
-            Files.copy(source, target);
-        }
-
-    }
-
-
-    /**
-     * Run test with --module-path.
-     *
-     * BananaScriptEngine should be found.
-     */
-    public void runWithModulePath() throws Exception {
-        int exitValue
-            = executeTestJava("--module-path", MODS_DIR.toString(),
-                              "--add-modules", "bananascript",
-                              "-m", "test/test.Main",
-                              "BananaScriptEngine")
-                .outputTo(System.out)
-                .errorTo(System.out)
-                .getExitValue();
-
-        assertTrue(exitValue == 0);
-    }
-
-
-    /**
-     * Run test with --module-path and -classpath.
-     *
-     * Both BananaScriptEngine and PearScriptEngine should be found
-     */
-    public void runWithModulePathAndClassPath() throws Exception {
-        int exitValue
-            = executeTestJava("--module-path", MODS_DIR.toString(),
-                              "-cp", CLASSES_DIR.toString(),
-                              "--add-modules", "bananascript",
-                              "-m", "test/test.Main",
-                              "BananaScriptEngine", "PearScriptEngine")
-                .outputTo(System.out)
-                .errorTo(System.out)
-                .getExitValue();
-
-        assertTrue(exitValue == 0);
-    }
-
-
-    /**
-     * Exercise ServiceLoader.load(Layer, Class).
-     */
-    public void testWithCustomLayer() throws Exception {
-
-        ServiceLoader<ScriptEngineFactory> sl;
-
-        // BananaScriptEngine should not be in the boot Layer
-        sl = ServiceLoader.load(Layer.boot(), ScriptEngineFactory.class);
-        assertTrue(find("BananaScriptEngine", sl) == null);
-
-        // create a custom Layer
-        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
-        Layer bootLayer = Layer.boot();
-        Configuration parent = bootLayer.configuration();
-        Configuration cf
-            = parent.resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of());
-        ClassLoader scl = ClassLoader.getSystemClassLoader();
-        Layer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
-
-        assertTrue(layer.findModule("bananascript").isPresent());
-        ClassLoader loader = layer.findLoader("bananascript");
-
-        sl = ServiceLoader.load(layer, ScriptEngineFactory.class);
-        ScriptEngineFactory factory = find("BananaScriptEngine", sl);
-        assertTrue(factory != null);
-        assertEquals(factory.getClass().getModule().getName(), "bananascript");
-        assertTrue(factory.getClass().getClassLoader() == loader);
-
-    }
-
-    /**
-     * Find the given scripting engine (by name) via the ScriptEngineFactory
-     * that ServiceLoader has found.
-     */
-    static ScriptEngineFactory find(String name,
-                                    ServiceLoader<ScriptEngineFactory> sl) {
-        for (ScriptEngineFactory factory : sl) {
-            if (factory.getEngineName().equals(name))
-                return factory;
-        }
-        return null;
-    }
-
-
-}
-
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/badreturntype/ProviderFactory.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/badreturntype/ProviderFactory.java
index 789cdb9..86ca004 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/badreturntype/ProviderFactory.java
@@ -21,13 +21,18 @@
  * questions.
  */
 
-package p7;
+package p;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+/**
+ * A provider factory with a provider() method with a return type that is not
+ * p.Service
+ */
+
+public class ProviderFactory {
+    ProviderFactory() { }
+
+    public static Object provider() {
+        throw new RuntimeException("Should not be called");
     }
 }
+
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/ProviderFactory.java
similarity index 81%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/ProviderFactory.java
index 4c3b290..3ec2391 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/ProviderFactory.java
@@ -21,9 +21,17 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+package p;
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+/**
+ * Not a provider factory because the class is not public.
+ */
+
+class ProviderFactory {
+    ProviderFactory() { }
+
+    public static Service provider() {
+        throw new RuntimeException("Should not be called");
+    }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/classnotpublic/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/ProviderFactory.java
similarity index 80%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/ProviderFactory.java
index 789cdb9..249593d 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/ProviderFactory.java
@@ -21,13 +21,17 @@
  * questions.
  */
 
-package p7;
+package p;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+/**
+ * Not a provider factory because the static provider() method is not public.
+ */
+
+public class ProviderFactory {
+    ProviderFactory() { }
+
+    static Service provider() {
+        throw new RuntimeException("Should not be called");
     }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/methodnotpublic/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/ProviderFactory.java
similarity index 81%
copy from langtools/test/tools/jdeps/modules/src/m7/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/ProviderFactory.java
index 408efc2..73eaedc 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/ProviderFactory.java
@@ -21,9 +21,18 @@
  * questions.
  */
 
-module m7 {
-    // only use classes that have no direct or indirect dependency
-    // to sun.misc.Unsafe
-    requires unsafe;
-    requires m6;
+package p;
+
+/**
+ * A provider factory that defines a public static provider method that returns
+ * null.
+ */
+
+public class ProviderFactory {
+    ProviderFactory() { }
+
+    public static Service provider() {
+        return null;
+    }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/returnsnull/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/ProviderFactory.java
similarity index 82%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/ProviderFactory.java
index 242f168..3eb8eeb 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/ProviderFactory.java
@@ -21,5 +21,17 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package p;
+
+/**
+ * A provider factory that throws an exception.
+ */
+
+public class ProviderFactory {
+    ProviderFactory() { }
+
+    public static Service provider() {
+        throw new RuntimeException();
+    }
+}
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badfactories/throwsexception/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Provider.java
similarity index 88%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Provider.java
index 4c3b290..8b38169 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Provider.java
@@ -21,9 +21,13 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+package p;
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+/**
+ * A provider class with a non-public constructor
+ */
+
+public class Provider implements Service {
+    Provider() { }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/ctornotpublic/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/notasubtype/Provider.java
similarity index 89%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/notasubtype/Provider.java
index 4c3b290..a684e47 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/notasubtype/Provider.java
@@ -21,9 +21,13 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+package p;
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+/**
+ * A provider class that is not a subtype of Service.
+ */
+
+public class Provider {
+    Provider() { }
 }
+
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Provider.java
similarity index 89%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Provider.java
index 242f168..7d6cd6a 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Provider.java
@@ -21,5 +21,13 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package p;
+
+/**
+ * Provider class not public.
+ */
+
+class Provider implements Service {
+    public Provider() { }
+}
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/notpublic/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Provider.java
similarity index 85%
copy from langtools/test/tools/jdeps/modules/src/m7/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Provider.java
index 408efc2..2a9092f 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Provider.java
@@ -21,9 +21,15 @@
  * questions.
  */
 
-module m7 {
-    // only use classes that have no direct or indirect dependency
-    // to sun.misc.Unsafe
-    requires unsafe;
-    requires m6;
+package p;
+
+/**
+ * A provider class with a constructor throws an exception.
+ */
+
+public class Provider {
+    public Provider() {
+        throw new RuntimeException();
+    }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Service.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Service.java
index 9d2c8be..e8394be 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/badproviders/throwsexception/Service.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+public interface Service { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/bananascript/module-info.java b/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java
similarity index 90%
rename from jdk/test/java/util/ServiceLoader/modules/src/bananascript/module-info.java
rename to jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java
index d599d44..3ed6f7b 100644
--- a/jdk/test/java/util/ServiceLoader/modules/src/bananascript/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/module-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,6 @@
     requires java.scripting;
 
     provides javax.script.ScriptEngineFactory
-      with org.banana.BananaScriptEngineFactory;
+        with org.banana.BananaScriptEngineFactory;
 }
 
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScript.java b/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScript.java
similarity index 100%
rename from jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScript.java
rename to jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScript.java
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScriptEngineFactory.java b/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java
similarity index 87%
rename from jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScriptEngineFactory.java
rename to jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java
index 443415c..2f68f9e 100644
--- a/jdk/test/java/util/ServiceLoader/modules/src/bananascript/org/banana/BananaScriptEngineFactory.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/bananascript/org/banana/BananaScriptEngineFactory.java
@@ -30,6 +30,18 @@
 
 public class BananaScriptEngineFactory implements ScriptEngineFactory {
 
+    static final BananaScriptEngineFactory INSTANCE  = new BananaScriptEngineFactory(null);
+
+    public BananaScriptEngineFactory() {
+        throw new RuntimeException("Should not be called");
+    }
+
+    private BananaScriptEngineFactory(Void param) { }
+
+    public static BananaScriptEngineFactory provider() {
+        return INSTANCE;
+    }
+
     @Override
     public String getEngineName() {
         return "BananaScriptEngine";
diff --git a/langtools/test/tools/jdeps/modules/src/m7/module-info.java b/jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java
similarity index 85%
copy from langtools/test/tools/jdeps/modules/src/m7/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java
index 408efc2..d65b467 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/test1/module-info.java
@@ -21,9 +21,13 @@
  * questions.
  */
 
-module m7 {
-    // only use classes that have no direct or indirect dependency
-    // to sun.misc.Unsafe
-    requires unsafe;
-    requires m6;
+/**
+ * Test module that provides an implementation of p.Service via a
+ * provider factory class.
+ */
+
+module test1 {
+    exports p;
+    provides p.Service with p.ProviderFactory;
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m7/module-info.java b/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java
similarity index 81%
copy from langtools/test/tools/jdeps/modules/src/m7/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java
index 408efc2..c2f988a 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/ProviderFactory.java
@@ -21,9 +21,18 @@
  * questions.
  */
 
-module m7 {
-    // only use classes that have no direct or indirect dependency
-    // to sun.misc.Unsafe
-    requires unsafe;
-    requires m6;
+package p;
+
+/**
+ * Provider factory
+ */
+public class ProviderFactory {
+    ProviderFactory() { }
+
+    private static final Service INSTANCE = new Service() { };
+
+    public static Service provider() {
+        return INSTANCE;
+    }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java
index 9d2c8be..c002395 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/test1/p/Service.java
@@ -21,7 +21,9 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+/**
+ * Service type
+ */
+public interface Service { }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java
similarity index 87%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java
index 242f168..473df98 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/test2/module-info.java
@@ -21,5 +21,12 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+/**
+ * Test module that provides an implementation of p.Service.
+ */
+
+module test2 {
+    exports p;
+    provides p.Service with p.Provider;
+}
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java
similarity index 90%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java
index 9d2c8be..42e1bdf 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Provider.java
@@ -21,7 +21,12 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+package p;
+
+/**
+ * Provider type
+ */
+public class Provider implements Service {
+    public Provider() { }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java
index 9d2c8be..c002395 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/java/util/ServiceLoader/modules/modules/test2/p/Service.java
@@ -21,7 +21,9 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+package p;
+
+/**
+ * Service type
+ */
+public interface Service { }
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java
index c00c4b1..c731ff1 100644
--- a/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java
+++ b/jdk/test/java/util/ServiceLoader/modules/src/pearscript/org/pear/PearScriptEngineFactory.java
@@ -30,6 +30,12 @@
 
 public class PearScriptEngineFactory implements ScriptEngineFactory {
 
+    public PearScriptEngineFactory() { }
+
+    public static PearScriptEngineFactory provider() {
+        throw new RuntimeException("Should not be called");
+    }
+
     @Override
     public String getEngineName() {
         return "PearScriptEngine";
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/test/module-info.java b/jdk/test/java/util/ServiceLoader/modules/src/test/module-info.java
deleted file mode 100644
index a43887c..0000000
--- a/jdk/test/java/util/ServiceLoader/modules/src/test/module-info.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 test {
-    requires java.scripting;
-
-    uses javax.script.ScriptEngineFactory;
-}
-
diff --git a/jdk/test/java/util/ServiceLoader/modules/src/test/test/Main.java b/jdk/test/java/util/ServiceLoader/modules/src/test/test/Main.java
deleted file mode 100644
index a03d8eb..0000000
--- a/jdk/test/java/util/ServiceLoader/modules/src/test/test/Main.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 test;
-
-import java.util.HashSet;
-import java.util.ServiceLoader;
-import java.util.Set;
-import javax.script.ScriptEngineFactory;
-
-public class Main {
-    public static void main(String[] args) {
-        Set<String> engines = new HashSet<>();
-        for (ScriptEngineFactory factory: ServiceLoader.load(ScriptEngineFactory.class)) {
-            System.out.format("loaded: %s%n" , factory.getEngineName());
-            engines.add(factory.getEngineName());
-        }
-
-        for (String engine: args) {
-            if (!engines.contains(engine))
-                throw new RuntimeException(engine + " not found");
-        }
-    }
-}
diff --git a/jdk/test/java/util/Spliterator/SpliteratorFailFastTest.java b/jdk/test/java/util/Spliterator/SpliteratorFailFastTest.java
new file mode 100644
index 0000000..a0e71d2
--- /dev/null
+++ b/jdk/test/java/util/Spliterator/SpliteratorFailFastTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Spliterator;
+import java.util.Stack;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.WeakHashMap;
+import java.util.function.Supplier;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @bug 8148748
+ * @summary Spliterator fail-fast tests
+ * @run testng SpliteratorFailFastTest
+ */
+
+@Test
+public class SpliteratorFailFastTest extends SpliteratorLateBindingFailFastHelper {
+
+    static Object[][] spliteratorDataProvider;
+
+    @DataProvider(name = "Source")
+    public static Object[][] spliteratorDataProvider() {
+        if (spliteratorDataProvider != null) {
+            return spliteratorDataProvider;
+        }
+
+        List<Object[]> data = new ArrayList<>();
+        SpliteratorDataBuilder<Integer> db =
+                new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
+
+        // Collections
+
+        db.addList(ArrayList::new);
+
+        db.addList(LinkedList::new);
+
+        db.addList(Vector::new);
+
+        db.addList(AbstractRandomAccessListImpl::new);
+
+        db.addCollection(HashSet::new);
+
+        db.addCollection(LinkedHashSet::new);
+
+        db.addCollection(TreeSet::new);
+
+        db.addCollection(c -> {
+            Stack<Integer> s = new Stack<>();
+            s.addAll(c);
+            return s;
+        });
+
+        db.addCollection(PriorityQueue::new);
+
+        // ArrayDeque fails some tests since its fail-fast support is weaker
+        // than other collections and limited to detecting most, but not all,
+        // removals.  It probably requires its own test since it is difficult
+        // to abstract out the conditions under which it fails-fast.
+//        db.addCollection(ArrayDeque::new);
+
+        // Maps
+
+        db.addMap(HashMap::new);
+
+        db.addMap(LinkedHashMap::new);
+
+        // This fails when run through jtreg but passes when run through
+        // ant
+//        db.addMap(IdentityHashMap::new);
+
+        db.addMap(WeakHashMap::new);
+
+        // @@@  Descending maps etc
+        db.addMap(TreeMap::new);
+
+        return spliteratorDataProvider = data.toArray(new Object[0][]);
+    }
+
+    @Test(dataProvider = "Source")
+    public <T> void testTryAdvance(String description, Supplier<Source<T>> ss) {
+        {
+            Source<T> source = ss.get();
+            Spliterator<T> s = source.spliterator();
+
+            s.tryAdvance(e -> {
+            });
+            source.update();
+
+            executeAndCatch(() -> s.tryAdvance(e -> {
+            }));
+        }
+
+        {
+            Source<T> source = ss.get();
+            Spliterator<T> s = source.spliterator();
+
+            s.tryAdvance(e -> {
+            });
+            source.update();
+
+            executeAndCatch(() -> s.forEachRemaining(e -> {
+            }));
+        }
+    }
+
+    @Test(dataProvider = "Source")
+    public <T> void testForEach(String description, Supplier<Source<T>> ss) {
+        Source<T> source = ss.get();
+        Spliterator<T> s = source.spliterator();
+
+        executeAndCatch(() -> s.forEachRemaining(e -> {
+            source.update();
+        }));
+    }
+
+    @Test(dataProvider = "Source")
+    public <T> void testEstimateSize(String description, Supplier<Source<T>> ss) {
+        {
+            Source<T> source = ss.get();
+            Spliterator<T> s = source.spliterator();
+
+            s.estimateSize();
+            source.update();
+
+            executeAndCatch(() -> s.tryAdvance(e -> {
+            }));
+        }
+
+        {
+            Source<T> source = ss.get();
+            Spliterator<T> s = source.spliterator();
+
+            s.estimateSize();
+            source.update();
+
+            executeAndCatch(() -> s.forEachRemaining(e -> {
+            }));
+        }
+    }
+
+    private void executeAndCatch(Runnable r) {
+        executeAndCatch(ConcurrentModificationException.class, r);
+    }
+
+    private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
+        Exception caught = null;
+        try {
+            r.run();
+        }
+        catch (Exception e) {
+            caught = e;
+        }
+
+        assertNotNull(caught,
+                      String.format("No Exception was thrown, expected an Exception of %s to be thrown",
+                                    expected.getName()));
+        assertTrue(expected.isInstance(caught),
+                   String.format("Exception thrown %s not an instance of %s",
+                                 caught.getClass().getName(), expected.getName()));
+    }
+
+}
diff --git a/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastHelper.java b/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastHelper.java
new file mode 100644
index 0000000..a3c53b7
--- /dev/null
+++ b/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastHelper.java
@@ -0,0 +1,224 @@
+/*
+ * 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.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.RandomAccess;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+class SpliteratorLateBindingFailFastHelper {
+
+    interface Source<T> {
+        Spliterator<T> spliterator();
+
+        void update();
+
+        default boolean bindOnCharacteristics() {
+            return false;
+        }
+    }
+
+    static class IntSource<T> implements Source<Integer> {
+        final T b;
+        final Function<? super T, Spliterator.OfInt> toSpliterator;
+        final Consumer<T> updater;
+        final boolean bindOnCharacteristics;
+
+        public IntSource(T b, Function<? super T, Spliterator.OfInt> toSpliterator,
+                         Consumer<T> updater) {
+            this(b, toSpliterator, updater, false);
+        }
+
+        public IntSource(T b, Function<? super T, Spliterator.OfInt> toSpliterator,
+                         Consumer<T> updater, boolean bindOnCharacteristics) {
+            this.b = b;
+            this.toSpliterator = toSpliterator;
+            this.updater = updater;
+            this.bindOnCharacteristics = bindOnCharacteristics;
+        }
+
+        @Override
+        public Spliterator.OfInt spliterator() {
+            return toSpliterator.apply(b);
+        }
+
+        @Override
+        public void update() {
+            updater.accept(b);
+        }
+
+        @Override
+        public boolean bindOnCharacteristics() {
+            return bindOnCharacteristics;
+        }
+    }
+
+    static class SpliteratorDataBuilder<T> {
+        final List<Object[]> data;
+
+        final T newValue;
+
+        final List<T> exp;
+
+        final Map<T, T> mExp;
+
+        SpliteratorDataBuilder(List<Object[]> data, T newValue, List<T> exp) {
+            this.data = data;
+            this.newValue = newValue;
+            this.exp = exp;
+            this.mExp = createMap(exp);
+        }
+
+        Map<T, T> createMap(List<T> l) {
+            Map<T, T> m = new LinkedHashMap<>();
+            for (T t : l) {
+                m.put(t, t);
+            }
+            return m;
+        }
+
+        void add(String description, Supplier<Source<?>> s) {
+            data.add(new Object[]{description, s});
+        }
+
+        void addCollection(Function<Collection<T>, ? extends Collection<T>> f) {
+            class CollectionSource implements Source<T> {
+                final Collection<T> c = f.apply(exp);
+
+                final Consumer<Collection<T>> updater;
+
+                CollectionSource(Consumer<Collection<T>> updater) {
+                    this.updater = updater;
+                }
+
+                @Override
+                public Spliterator<T> spliterator() {
+                    return c.spliterator();
+                }
+
+                @Override
+                public void update() {
+                    updater.accept(c);
+                }
+            }
+
+            String description = "new " + f.apply(Collections.<T>emptyList()).getClass().getName() + ".spliterator() ";
+            add(description + "ADD", () -> new CollectionSource(c -> c.add(newValue)));
+            add(description + "REMOVE", () -> new CollectionSource(c -> c.remove(c.iterator().next())));
+        }
+
+        void addList(Function<Collection<T>, ? extends List<T>> l) {
+            addCollection(l);
+            addCollection(l.andThen(list -> list.subList(0, list.size())));
+        }
+
+        void addMap(Function<Map<T, T>, ? extends Map<T, T>> mapConstructor) {
+            class MapSource<U> implements Source<U> {
+                final Map<T, T> m = mapConstructor.apply(mExp);
+
+                final Collection<U> c;
+
+                final Consumer<Map<T, T>> updater;
+
+                MapSource(Function<Map<T, T>, Collection<U>> f, Consumer<Map<T, T>> updater) {
+                    this.c = f.apply(m);
+                    this.updater = updater;
+                }
+
+                @Override
+                public Spliterator<U> spliterator() {
+                    return c.spliterator();
+                }
+
+                @Override
+                public void update() {
+                    updater.accept(m);
+                }
+            }
+
+            Map<String, Consumer<Map<T, T>>> actions = new HashMap<>();
+            actions.put("ADD", m -> m.put(newValue, newValue));
+            actions.put("REMOVE", m -> m.remove(m.keySet().iterator().next()));
+
+            String description = "new " + mapConstructor.apply(Collections.<T, T>emptyMap()).getClass().getName();
+            for (Map.Entry<String, Consumer<Map<T, T>>> e : actions.entrySet()) {
+                add(description + ".keySet().spliterator() " + e.getKey(),
+                    () -> new MapSource<>(m -> m.keySet(), e.getValue()));
+                add(description + ".values().spliterator() " + e.getKey(),
+                    () -> new MapSource<>(m -> m.values(), e.getValue()));
+                add(description + ".entrySet().spliterator() " + e.getKey(),
+                    () -> new MapSource<>(m -> m.entrySet(), e.getValue()));
+            }
+        }
+    }
+
+    static class AbstractRandomAccessListImpl extends AbstractList<Integer> implements RandomAccess {
+        List<Integer> l;
+
+        AbstractRandomAccessListImpl(Collection<Integer> c) {
+            this.l = new ArrayList<>(c);
+        }
+
+        @Override
+        public boolean add(Integer integer) {
+            modCount++;
+            return l.add(integer);
+        }
+
+        @Override
+        public Iterator<Integer> iterator() {
+            return l.iterator();
+        }
+
+        @Override
+        public Integer get(int index) {
+            return l.get(index);
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            modCount++;
+            return l.remove(o);
+        }
+
+        @Override
+        public int size() {
+            return l.size();
+        }
+
+        @Override
+        public List<Integer> subList(int fromIndex, int toIndex) {
+            return l.subList(fromIndex, toIndex);
+        }
+    }
+}
diff --git a/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java b/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java
deleted file mode 100644
index 0aecca6..0000000
--- a/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.PriorityQueue;
-import java.util.RandomAccess;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.Stack;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.Vector;
-import java.util.WeakHashMap;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-import static org.testng.Assert.*;
-
-/**
- * @test
- * @bug 8148748
- * @summary Spliterator last-binding and fail-fast tests
- * @run testng SpliteratorLateBindingFailFastTest
- */
-
-@Test
-public class SpliteratorLateBindingFailFastTest {
-
-    private interface Source<T> {
-        Collection<T> asCollection();
-        void update();
-    }
-
-    private static class SpliteratorDataBuilder<T> {
-        final List<Object[]> data;
-
-        final T newValue;
-
-        final List<T> exp;
-
-        final Map<T, T> mExp;
-
-        SpliteratorDataBuilder(List<Object[]> data, T newValue, List<T> exp) {
-            this.data = data;
-            this.newValue = newValue;
-            this.exp = exp;
-            this.mExp = createMap(exp);
-        }
-
-        Map<T, T> createMap(List<T> l) {
-            Map<T, T> m = new LinkedHashMap<>();
-            for (T t : l) {
-                m.put(t, t);
-            }
-            return m;
-        }
-
-        void add(String description, Supplier<Source<?>> s) {
-            description = joiner(description).toString();
-            data.add(new Object[]{description, s});
-        }
-
-        void addCollection(Function<Collection<T>, ? extends Collection<T>> f) {
-            class CollectionSource implements Source<T> {
-                final Collection<T> c = f.apply(exp);
-
-                final Consumer<Collection<T>> updater;
-
-                CollectionSource(Consumer<Collection<T>> updater) {
-                    this.updater = updater;
-                }
-
-                @Override
-                public Collection<T> asCollection() {
-                    return c;
-                }
-
-                @Override
-                public void update() {
-                    updater.accept(c);
-                }
-            }
-
-            String description = "new " + f.apply(Collections.<T>emptyList()).getClass().getName() + ".spliterator() ";
-            add(description + "ADD", () -> new CollectionSource(c -> c.add(newValue)));
-            add(description + "REMOVE", () -> new CollectionSource(c -> c.remove(c.iterator().next())));
-        }
-
-        void addList(Function<Collection<T>, ? extends List<T>> l) {
-            addCollection(l);
-            addCollection(l.andThen(list -> list.subList(0, list.size())));
-        }
-
-        void addMap(Function<Map<T, T>, ? extends Map<T, T>> mapConstructor) {
-            class MapSource<U> implements Source<U> {
-                final Map<T, T> m = mapConstructor.apply(mExp);
-
-                final Collection<U> c;
-
-                final Consumer<Map<T, T>> updater;
-
-                MapSource(Function<Map<T, T>, Collection<U>> f, Consumer<Map<T, T>> updater) {
-                    this.c = f.apply(m);
-                    this.updater = updater;
-                }
-
-                @Override
-                public Collection<U> asCollection() {
-                    return c;
-                }
-
-                @Override
-                public void update() {
-                    updater.accept(m);
-                }
-            }
-
-            Map<String, Consumer<Map<T, T>>> actions = new HashMap<>();
-            actions.put("ADD", m -> m.put(newValue, newValue));
-            actions.put("REMOVE", m -> m.remove(m.keySet().iterator().next()));
-
-            String description = "new " + mapConstructor.apply(Collections.<T, T>emptyMap()).getClass().getName();
-            for (Map.Entry<String, Consumer<Map<T, T>>> e : actions.entrySet()) {
-                add(description + ".keySet().spliterator() " + e.getKey(),
-                    () -> new MapSource<T>(m -> m.keySet(), e.getValue()));
-                add(description + ".values().spliterator() " + e.getKey(),
-                    () -> new MapSource<T>(m -> m.values(), e.getValue()));
-                add(description + ".entrySet().spliterator() " + e.getKey(),
-                    () -> new MapSource<Map.Entry<T, T>>(m -> m.entrySet(), e.getValue()));
-            }
-        }
-
-        StringBuilder joiner(String description) {
-            return new StringBuilder(description).
-                    append(" {").
-                    append("size=").append(exp.size()).
-                    append("}");
-        }
-    }
-
-    static Object[][] spliteratorDataProvider;
-
-    @DataProvider(name = "Source")
-    public static Object[][] spliteratorDataProvider() {
-        if (spliteratorDataProvider != null) {
-            return spliteratorDataProvider;
-        }
-
-        List<Object[]> data = new ArrayList<>();
-        SpliteratorDataBuilder<Integer> db = new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
-
-        // Collections
-
-        db.addList(ArrayList::new);
-
-        db.addList(LinkedList::new);
-
-        db.addList(Vector::new);
-
-        class AbstractRandomAccessListImpl extends AbstractList<Integer> implements RandomAccess {
-            List<Integer> l;
-
-            AbstractRandomAccessListImpl(Collection<Integer> c) {
-                this.l = new ArrayList<>(c);
-            }
-
-            @Override
-            public boolean add(Integer integer) {
-                modCount++;
-                return l.add(integer);
-            }
-
-            @Override
-            public Iterator<Integer> iterator() {
-                return l.iterator();
-            }
-
-            @Override
-            public Integer get(int index) {
-                return l.get(index);
-            }
-
-            @Override
-            public boolean remove(Object o) {
-                modCount++;
-                return l.remove(o);
-            }
-
-            @Override
-            public int size() {
-                return l.size();
-            }
-
-            @Override
-            public List<Integer> subList(int fromIndex, int toIndex) {
-                return l.subList(fromIndex, toIndex);
-            }
-        }
-        db.addList(AbstractRandomAccessListImpl::new);
-
-        db.addCollection(HashSet::new);
-
-        db.addCollection(LinkedHashSet::new);
-
-        db.addCollection(TreeSet::new);
-
-
-        db.addCollection(c -> { Stack<Integer> s = new Stack<>(); s.addAll(c); return s;});
-
-        db.addCollection(PriorityQueue::new);
-
-        // ArrayDeque fails some tests since its fail-fast support is weaker
-        // than other collections and limited to detecting most, but not all,
-        // removals.  It probably requires its own test since it is difficult
-        // to abstract out the conditions under which it fails-fast.
-//        db.addCollection(ArrayDeque::new);
-
-        // Maps
-
-        db.addMap(HashMap::new);
-
-        db.addMap(LinkedHashMap::new);
-
-        // This fails when run through jtreg but passes when run through
-        // ant
-//        db.addMap(IdentityHashMap::new);
-
-        db.addMap(WeakHashMap::new);
-
-        // @@@  Descending maps etc
-        db.addMap(TreeMap::new);
-
-        return spliteratorDataProvider = data.toArray(new Object[0][]);
-    }
-
-    @Test(dataProvider = "Source")
-    public <T> void lateBindingTestWithForEach(String description, Supplier<Source<T>> ss) {
-        Source<T> source = ss.get();
-        Collection<T> c = source.asCollection();
-        Spliterator<T> s = c.spliterator();
-
-        source.update();
-
-        Set<T> r = new HashSet<>();
-        s.forEachRemaining(r::add);
-
-        assertEquals(r, new HashSet<>(c));
-    }
-
-    @Test(dataProvider = "Source")
-    public <T> void lateBindingTestWithTryAdvance(String description, Supplier<Source<T>> ss) {
-        Source<T> source = ss.get();
-        Collection<T> c = source.asCollection();
-        Spliterator<T> s = c.spliterator();
-
-        source.update();
-
-        Set<T> r = new HashSet<>();
-        while (s.tryAdvance(r::add)) { }
-
-        assertEquals(r, new HashSet<>(c));
-    }
-
-    @Test(dataProvider = "Source")
-    public <T> void lateBindingTestWithCharacteritics(String description, Supplier<Source<T>> ss) {
-        Source<T> source = ss.get();
-        Collection<T> c = source.asCollection();
-        Spliterator<T> s = c.spliterator();
-        s.characteristics();
-
-        Set<T> r = new HashSet<>();
-        s.forEachRemaining(r::add);
-
-        assertEquals(r, new HashSet<>(c));
-    }
-
-
-    @Test(dataProvider = "Source")
-    public <T> void testFailFastTestWithTryAdvance(String description, Supplier<Source<T>> ss) {
-        {
-            Source<T> source = ss.get();
-            Collection<T> c = source.asCollection();
-            Spliterator<T> s = c.spliterator();
-
-            s.tryAdvance(e -> {
-            });
-            source.update();
-
-            executeAndCatch(() -> s.tryAdvance(e -> { }));
-        }
-
-        {
-            Source<T> source = ss.get();
-            Collection<T> c = source.asCollection();
-            Spliterator<T> s = c.spliterator();
-
-            s.tryAdvance(e -> {
-            });
-            source.update();
-
-            executeAndCatch(() -> s.forEachRemaining(e -> {
-            }));
-        }
-    }
-
-    @Test(dataProvider = "Source")
-    public <T> void testFailFastTestWithForEach(String description, Supplier<Source<T>> ss) {
-        Source<T> source = ss.get();
-        Collection<T> c = source.asCollection();
-        Spliterator<T> s = c.spliterator();
-
-        executeAndCatch(() -> s.forEachRemaining(e -> {
-            source.update();
-        }));
-    }
-
-    @Test(dataProvider = "Source")
-    public <T> void testFailFastTestWithEstimateSize(String description, Supplier<Source<T>> ss) {
-        {
-            Source<T> source = ss.get();
-            Collection<T> c = source.asCollection();
-            Spliterator<T> s = c.spliterator();
-
-            s.estimateSize();
-            source.update();
-
-            executeAndCatch(() -> s.tryAdvance(e -> { }));
-        }
-
-        {
-            Source<T> source = ss.get();
-            Collection<T> c = source.asCollection();
-            Spliterator<T> s = c.spliterator();
-
-            s.estimateSize();
-            source.update();
-
-            executeAndCatch(() -> s.forEachRemaining(e -> {
-            }));
-        }
-    }
-
-    private void executeAndCatch(Runnable r) {
-        executeAndCatch(ConcurrentModificationException.class, r);
-    }
-
-    private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
-        Exception caught = null;
-        try {
-            r.run();
-        }
-        catch (Exception e) {
-            caught = e;
-        }
-
-        assertNotNull(caught,
-                      String.format("No Exception was thrown, expected an Exception of %s to be thrown",
-                                    expected.getName()));
-        assertTrue(expected.isInstance(caught),
-                   String.format("Exception thrown %s not an instance of %s",
-                                 caught.getClass().getName(), expected.getName()));
-    }
-
-}
diff --git a/jdk/test/java/util/Spliterator/SpliteratorLateBindingTest.java b/jdk/test/java/util/Spliterator/SpliteratorLateBindingTest.java
new file mode 100644
index 0000000..42553cb
--- /dev/null
+++ b/jdk/test/java/util/Spliterator/SpliteratorLateBindingTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.nio.CharBuffer;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.Stack;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.WeakHashMap;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @test
+ * @bug 8148748 8170155
+ * @summary Spliterator last-binding tests
+ * @run testng SpliteratorLateBindingTest
+ */
+
+@Test
+public class SpliteratorLateBindingTest extends SpliteratorLateBindingFailFastHelper {
+
+    static Object[][] spliteratorDataProvider;
+
+    @DataProvider(name = "Source")
+    public static Object[][] sourceDataProvider() {
+        if (spliteratorDataProvider != null) {
+            return spliteratorDataProvider;
+        }
+
+        List<Object[]> data = new ArrayList<>();
+        SpliteratorDataBuilder<Integer> db =
+                new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
+
+        // Collections
+
+        db.addList(ArrayList::new);
+
+        db.addList(LinkedList::new);
+
+        db.addList(Vector::new);
+
+        db.addList(AbstractRandomAccessListImpl::new);
+
+        db.addCollection(HashSet::new);
+
+        db.addCollection(LinkedHashSet::new);
+
+        db.addCollection(TreeSet::new);
+
+        db.addCollection(c -> {
+            Stack<Integer> s = new Stack<>();
+            s.addAll(c);
+            return s;
+        });
+
+        db.addCollection(PriorityQueue::new);
+
+        db.addCollection(ArrayDeque::new);
+
+        // Maps
+
+        db.addMap(HashMap::new);
+
+        db.addMap(LinkedHashMap::new);
+
+        db.addMap(IdentityHashMap::new);
+
+        db.addMap(WeakHashMap::new);
+
+        // @@@  Descending maps etc
+        db.addMap(TreeMap::new);
+
+        // BitSet
+
+        List<Integer> bits = List.of(0, 1, 2);
+        Function<BitSet, Spliterator.OfInt> bitsSource = bs -> bs.stream().spliterator();
+        db.add("new BitSet.stream().spliterator() ADD",
+               () -> new IntSource<>(toBitSet(bits), bitsSource, bs -> bs.set(3)));
+        db.add("new BitSet.stream().spliterator() REMOVE",
+               () -> new IntSource<>(toBitSet(bits), bitsSource, bs -> bs.clear(2)));
+
+        // CharSequence
+
+        Function<CharSequence, Spliterator.OfInt> charsSource = sb -> sb.chars().spliterator();
+        Function<CharSequence, Spliterator.OfInt> pointsSource = sb -> sb.codePoints().spliterator();
+
+        db.add("new StringBuilder.chars().spliterator() ADD",
+               () -> new IntSource<>(new StringBuilder("ABC"), charsSource, bs -> bs.append("D"), true));
+        db.add("new StringBuilder.chars().spliterator() REMOVE",
+               () -> new IntSource<>(new StringBuilder("ABC"), charsSource, bs -> bs.deleteCharAt(2), true));
+        db.add("new StringBuilder.codePoints().spliterator() ADD",
+               () -> new IntSource<>(new StringBuilder("ABC"), pointsSource, bs -> bs.append("D"), true));
+        db.add("new StringBuilder.codePoints().spliterator() REMOVE",
+               () -> new IntSource<>(new StringBuilder("ABC"), pointsSource, bs -> bs.deleteCharAt(2), true));
+
+        db.add("new StringBuffer.chars().spliterator() ADD",
+               () -> new IntSource<>(new StringBuffer("ABC"), charsSource, bs -> bs.append("D"), true));
+        db.add("new StringBuffer.chars().spliterator() REMOVE",
+               () -> new IntSource<>(new StringBuffer("ABC"), charsSource, bs -> bs.deleteCharAt(2), true));
+        db.add("new StringBuffer.codePoints().spliterator() ADD",
+               () -> new IntSource<>(new StringBuffer("ABC"), pointsSource, bs -> bs.append("D"), true));
+        db.add("new StringBuffer.codePoints().spliterator() REMOVE",
+               () -> new IntSource<>(new StringBuffer("ABC"), pointsSource, bs -> bs.deleteCharAt(2), true));
+
+        db.add("CharBuffer.wrap().chars().spliterator() ADD",
+               () -> new IntSource<>(CharBuffer.wrap("ABCD").limit(3), charsSource, bs -> bs.limit(4), true));
+        db.add("CharBuffer.wrap().chars().spliterator() REMOVE",
+               () -> new IntSource<>(CharBuffer.wrap("ABCD"), charsSource, bs -> bs.limit(3), true));
+        db.add("CharBuffer.wrap().codePoints().spliterator() ADD",
+               () -> new IntSource<>(CharBuffer.wrap("ABCD").limit(3), pointsSource, bs -> bs.limit(4), true));
+        db.add("CharBuffer.wrap().codePoints().spliterator() REMOVE",
+               () -> new IntSource<>(CharBuffer.wrap("ABCD"), pointsSource, bs -> bs.limit(3), true));
+
+        return spliteratorDataProvider = data.toArray(new Object[0][]);
+    }
+
+
+    @DataProvider(name = "Source.Non.Binding.Characteristics")
+    public static Object[][] sourceCharacteristicsDataProvider() {
+        return Stream.of(sourceDataProvider()).filter(tc -> {
+            @SuppressWarnings("unchecked")
+            Supplier<Source<?>> s = (Supplier<Source<?>>) tc[1];
+            return !s.get().bindOnCharacteristics();
+        }).toArray(Object[][]::new);
+    }
+
+    static BitSet toBitSet(List<Integer> bits) {
+        BitSet bs = new BitSet();
+        bits.forEach(bs::set);
+        return bs;
+    }
+
+
+    @Test(dataProvider = "Source")
+    public <T> void testForEach(String description, Supplier<Source<T>> ss) {
+        Source<T> source = ss.get();
+        Spliterator<T> s = source.spliterator();
+
+        source.update();
+
+        Set<T> a = new HashSet<>();
+        s.forEachRemaining(a::add);
+
+        Set<T> e = new HashSet<>();
+        source.spliterator().forEachRemaining(e::add);
+        assertEquals(a, e);
+    }
+
+    @Test(dataProvider = "Source")
+    public <T> void testTryAdvance(String description, Supplier<Source<T>> ss) {
+        Source<T> source = ss.get();
+        Spliterator<T> s = source.spliterator();
+
+        source.update();
+
+        Set<T> a = new HashSet<>();
+        while (s.tryAdvance(a::add)) {
+        }
+
+        Set<T> e = new HashSet<>();
+        source.spliterator().forEachRemaining(e::add);
+        assertEquals(a, e);
+    }
+
+    @Test(dataProvider = "Source.Non.Binding.Characteristics")
+    public <T> void testCharacteristics(String description, Supplier<Source<T>> ss) {
+        Source<T> source = ss.get();
+        Spliterator<T> s = source.spliterator();
+
+        s.characteristics();
+        source.update();
+
+        Set<T> a = new HashSet<>();
+        s.forEachRemaining(a::add);
+
+        Set<T> e = new HashSet<>();
+        source.spliterator().forEachRemaining(e::add);
+        assertEquals(a, e);
+    }
+}
diff --git a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
index 4742043..a8338ca 100644
--- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
+++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
@@ -31,6 +31,7 @@
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import java.nio.CharBuffer;
 import java.util.AbstractCollection;
 import java.util.AbstractList;
 import java.util.AbstractSet;
@@ -884,6 +885,7 @@
             cdb.add("new CharSequenceImpl(\"%s\")", CharSequenceImpl::new);
             cdb.add("new StringBuilder(\"%s\")", StringBuilder::new);
             cdb.add("new StringBuffer(\"%s\")", StringBuffer::new);
+            cdb.add("CharBuffer.wrap(\"%s\".toCharArray())", s -> CharBuffer.wrap(s.toCharArray()));
         }
 
 
diff --git a/jdk/test/java/util/TreeMap/HeadTailTypeError.java b/jdk/test/java/util/TreeMap/HeadTailTypeError.java
index cc23734..88d5ed8 100644
--- a/jdk/test/java/util/TreeMap/HeadTailTypeError.java
+++ b/jdk/test/java/util/TreeMap/HeadTailTypeError.java
@@ -22,10 +22,10 @@
  */
 
 /*
-   @test
-   @bug 4251519 4251520
-   @summary indexOf and lastIndex of used to let you look outside the
-            valid range in the backing array
+ * @test
+ * @bug 4251519 4251520
+ * @summary indexOf and lastIndex of used to let you look outside the
+ *          valid range in the backing array
  */
 
 import java.util.*;
diff --git a/jdk/test/java/util/Vector/LastIndexOf.java b/jdk/test/java/util/Vector/LastIndexOf.java
index 08b133e..1a783bd 100644
--- a/jdk/test/java/util/Vector/LastIndexOf.java
+++ b/jdk/test/java/util/Vector/LastIndexOf.java
@@ -22,10 +22,10 @@
  */
 
 /*
-   @test
-   @bug 4271588
-   @summary Vector.lastIndex(Object, int) used to let you look outside the
-            valid range in the backing array
+ * @test
+ * @bug 4271588
+ * @summary Vector.lastIndex(Object, int) used to let you look outside the
+ *          valid range in the backing array
  */
 
 import java.util.*;
diff --git a/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java b/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java
index 1fd7b3b..d7abe4d 100644
--- a/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java
+++ b/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java
@@ -42,23 +42,24 @@
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Queue;
-import java.util.Random;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadLocalRandom;
 
 /*
  * @test
  * @bug 7014263
+ * @modules java.base/java.util.concurrent:open
  * @summary White box testing of ArrayBlockingQueue iterators.
  */
 
 /**
- * Highly coupled to the implementation of ArrayBlockingQueue.
+ * Tightly coupled to the implementation of ArrayBlockingQueue.
  * Uses reflection to inspect queue and iterator state.
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
 public class IteratorConsistency {
-    final Random rnd = new Random();
+    final ThreadLocalRandom rnd = ThreadLocalRandom.current();
     final int CAPACITY = 20;
     Field itrsField;
     Field itemsField;
@@ -144,6 +145,10 @@
             check(!it.hasNext());
             check(isDetached(it));
         }
+        if (rnd.nextBoolean()) {
+            it.forEachRemaining(e -> { throw new AssertionError(); });
+            checkDetached(it);
+        }
         if (rnd.nextBoolean())
             try { it.next(); fail("should throw"); }
             catch (NoSuchElementException success) {}
diff --git a/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java b/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java
index 545201c..804cd08 100644
--- a/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java
+++ b/jdk/test/java/util/concurrent/BlockingQueue/LastElement.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6215625 7161229
+ * @modules java.base/java.util.concurrent:open
  * @summary Check correct behavior when last element is removed.
  * @author Martin Buchholz
  */
diff --git a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java
index 070ee1e..22d080d 100644
--- a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java
+++ b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java
@@ -35,6 +35,8 @@
 /*
  * @test
  * @bug 6236036 6264015
+ * @modules java.base/java.util.concurrent:open
+ *          java.base/java.util.concurrent.locks:open
  * @summary Checks for a memory leak when a sequence of aborted timed
  * waits occur without a signal.  Uses the strategy of detecting
  * changes in the size of the object graph retained by a root object.
diff --git a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java
index 558cfb6..b3c77e0 100644
--- a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java
+++ b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java
@@ -34,6 +34,8 @@
 /*
  * @test
  * @bug 8054446 8137184 8137185
+ * @modules java.base/java.util.concurrent:open
+ *          java.base/java.util.concurrent.locks:open
  * @summary Regression test for memory leak in remove(Object)
  */
 
diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java
index d3e6300..f181174 100644
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java
@@ -44,7 +44,6 @@
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Queue;
-import java.util.Random;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentLinkedDeque;
@@ -52,10 +51,11 @@
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.ThreadLocalRandom;
 
 @SuppressWarnings({"unchecked", "rawtypes"})
 public class IteratorWeakConsistency {
-    final Random rnd = new Random();
+    final ThreadLocalRandom rnd = ThreadLocalRandom.current();
 
     void test(String[] args) throws Throwable {
         test(new LinkedBlockingQueue());
@@ -72,6 +72,9 @@
         if (rnd.nextBoolean()) {
             check(!it.hasNext());
         }
+        if (rnd.nextBoolean()) {
+            it.forEachRemaining(e -> { throw new AssertionError(); });
+        }
         if (rnd.nextBoolean())
             try { it.next(); fail("should throw"); }
             catch (NoSuchElementException success) {}
diff --git a/jdk/test/java/util/concurrent/FutureTask/Throw.java b/jdk/test/java/util/concurrent/FutureTask/Throw.java
index 59d643b..9e0b453 100644
--- a/jdk/test/java/util/concurrent/FutureTask/Throw.java
+++ b/jdk/test/java/util/concurrent/FutureTask/Throw.java
@@ -140,8 +140,8 @@
             catch (Throwable t) {
                 if (k.isAssignableFrom(t.getClass())) pass();
                 else unexpected(t);}}
-    @SuppressWarnings("unchecked") static <T extends Throwable>
-        void uncheckedThrow(Throwable t) throws T {
+    @SuppressWarnings("unchecked")
+    static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
         throw (T)t; // rely on vacuous cast
     }
 }
diff --git a/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java b/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java
index 093d949..a08e37f 100644
--- a/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java
+++ b/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java
@@ -34,6 +34,7 @@
 
 /*
  * @test
+ * @modules java.base/java.util.concurrent:open
  * @summary Test Phaser phase integer overflow behavior
  */
 
diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java
index 87dfd6e..44ccbb3 100644
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java
@@ -36,6 +36,7 @@
  * @bug 8022642 8065320 8129861
  * @summary Ensure relative sanity when zero core threads
  * @library /lib/testlibrary/
+ * @modules java.base/java.util.concurrent:open
  */
 
 import static java.util.concurrent.TimeUnit.HOURS;
diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java
index 71862dc..ce5561e 100644
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java
@@ -247,7 +247,13 @@
                tg.activeCount() > 0)
             Thread.sleep(4);
         equal(tg.activeCount(), 0);
-        check(System.nanoTime() - t0 >= tpe.getKeepAliveTime(NANOSECONDS));
+
+        // The following assertion is almost always true, but may
+        // exceptionally not be during a transition from core count
+        // too high to allowCoreThreadTimeOut.  Users will never
+        // notice, and we accept the small loss of testability.
+        //
+        // check(System.nanoTime() - t0 >= tpe.getKeepAliveTime(NANOSECONDS));
 
         //report("idle", tpe);
 
diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
index 56a1c9c..8a492e7 100644
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
@@ -290,8 +290,8 @@
         try {realMain(args);} catch (Throwable t) {unexpected(t);}
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
         if (failed > 0) throw new AssertionError("Some tests failed");}
-    @SuppressWarnings("unchecked") static <T extends Throwable>
-        void uncheckedThrow(Throwable t) throws T {
+    @SuppressWarnings("unchecked")
+    static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
         throw (T)t; // rely on vacuous cast
     }
 }
diff --git a/jdk/test/java/util/concurrent/atomic/VMSupportsCS8.java b/jdk/test/java/util/concurrent/atomic/VMSupportsCS8.java
index 144e6d8..e50becd 100644
--- a/jdk/test/java/util/concurrent/atomic/VMSupportsCS8.java
+++ b/jdk/test/java/util/concurrent/atomic/VMSupportsCS8.java
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 4992443 4994819
+ * @modules java.base/java.util.concurrent.atomic:open
  * @run main VMSupportsCS8
  * @summary Checks that the value of VMSupportsCS8 matches system properties.
  */
diff --git a/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java b/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java
index b218ade..5ba9e86 100644
--- a/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java
+++ b/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java
@@ -35,6 +35,7 @@
 /*
  * @test
  * @bug 8004138
+ * @modules java.base/java.util.concurrent:open
  * @summary Checks that ForkJoinTask thrown exceptions are not leaked.
  * This whitebox test is sensitive to forkjoin implementation details.
  */
diff --git a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java
index 913aea7..104091e 100644
--- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java
+++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java
@@ -148,8 +148,8 @@
         try {realMain(args);} catch (Throwable t) {unexpected(t);}
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
         if (failed > 0) throw new AssertionError("Some tests failed");}
-    @SuppressWarnings("unchecked") static <T extends Throwable>
-        void uncheckedThrow(Throwable t) throws T {
+    @SuppressWarnings("unchecked")
+    static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
         throw (T)t; // rely on vacuous cast
     }
 }
diff --git a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java
index 9df1603..cb98398 100644
--- a/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/ArrayBlockingQueueTest.java
@@ -38,6 +38,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
@@ -46,45 +47,78 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadLocalRandom;
 
 import junit.framework.Test;
 
 public class ArrayBlockingQueueTest extends JSR166TestCase {
 
-    public static class Fair extends BlockingQueueTest {
-        protected BlockingQueue emptyCollection() {
-            return new ArrayBlockingQueue(SIZE, true);
-        }
-    }
-
-    public static class NonFair extends BlockingQueueTest {
-        protected BlockingQueue emptyCollection() {
-            return new ArrayBlockingQueue(SIZE, false);
-        }
-    }
-
     public static void main(String[] args) {
         main(suite(), args);
     }
 
     public static Test suite() {
-        return newTestSuite(ArrayBlockingQueueTest.class,
-                            new Fair().testSuite(),
-                            new NonFair().testSuite());
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return ArrayBlockingQueue.class; }
+            public Collection emptyCollection() {
+                boolean fair = ThreadLocalRandom.current().nextBoolean();
+                return populatedQueue(0, SIZE, 2 * SIZE, fair);
+            }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
+
+        return newTestSuite(
+            ArrayBlockingQueueTest.class,
+            new Fair().testSuite(),
+            new NonFair().testSuite(),
+            CollectionTest.testSuite(new Implementation()));
+    }
+
+    public static class Fair extends BlockingQueueTest {
+        protected BlockingQueue emptyCollection() {
+            return populatedQueue(0, SIZE, 2 * SIZE, true);
+        }
+    }
+
+    public static class NonFair extends BlockingQueueTest {
+        protected BlockingQueue emptyCollection() {
+            return populatedQueue(0, SIZE, 2 * SIZE, false);
+        }
     }
 
     /**
      * Returns a new queue of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
-    private ArrayBlockingQueue<Integer> populatedQueue(int n) {
-        ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(n);
+    static ArrayBlockingQueue<Integer> populatedQueue(int n) {
+        return populatedQueue(n, n, n, false);
+    }
+
+    /**
+     * Returns a new queue of given size containing consecutive
+     * Integers 0 ... n - 1, with given capacity range and fairness.
+     */
+    static ArrayBlockingQueue<Integer> populatedQueue(
+        int size, int minCapacity, int maxCapacity, boolean fair) {
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        int capacity = rnd.nextInt(minCapacity, maxCapacity + 1);
+        ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<>(capacity);
         assertTrue(q.isEmpty());
-        for (int i = 0; i < n; i++)
-            assertTrue(q.offer(new Integer(i)));
-        assertFalse(q.isEmpty());
-        assertEquals(0, q.remainingCapacity());
-        assertEquals(n, q.size());
+        // shuffle circular array elements so they wrap
+        {
+            int n = rnd.nextInt(capacity);
+            for (int i = 0; i < n; i++) q.add(42);
+            for (int i = 0; i < n; i++) q.remove();
+        }
+        for (int i = 0; i < size; i++)
+            assertTrue(q.offer((Integer) i));
+        assertEquals(size == 0, q.isEmpty());
+        assertEquals(capacity - size, q.remainingCapacity());
+        assertEquals(size, q.size());
+        if (size > 0)
+            assertEquals((Integer) 0, q.peek());
         return q;
     }
 
@@ -98,17 +132,25 @@
     /**
      * Constructor throws IAE if capacity argument nonpositive
      */
-    public void testConstructor2() {
-        try {
-            new ArrayBlockingQueue(0);
-            shouldThrow();
-        } catch (IllegalArgumentException success) {}
+    public void testConstructor_nonPositiveCapacity() {
+        for (int i : new int[] { 0, -1, Integer.MIN_VALUE }) {
+            try {
+                new ArrayBlockingQueue(i);
+                shouldThrow();
+            } catch (IllegalArgumentException success) {}
+            for (boolean fair : new boolean[] { true, false }) {
+                try {
+                    new ArrayBlockingQueue(i, fair);
+                    shouldThrow();
+                } catch (IllegalArgumentException success) {}
+            }
+        }
     }
 
     /**
      * Initializing from null Collection throws NPE
      */
-    public void testConstructor3() {
+    public void testConstructor_nullCollection() {
         try {
             new ArrayBlockingQueue(1, true, null);
             shouldThrow();
@@ -143,13 +185,13 @@
     /**
      * Initializing from too large collection throws IAE
      */
-    public void testConstructor6() {
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE; ++i)
-            ints[i] = i;
-        Collection<Integer> elements = Arrays.asList(ints);
+    public void testConstructor_collectionTooLarge() {
+        // just barely fits - succeeds
+        new ArrayBlockingQueue(SIZE, false,
+                               Collections.nCopies(SIZE, ""));
         try {
-            new ArrayBlockingQueue(SIZE - 1, false, elements);
+            new ArrayBlockingQueue(SIZE - 1, false,
+                                   Collections.nCopies(SIZE, ""));
             shouldThrow();
         } catch (IllegalArgumentException success) {}
     }
@@ -171,12 +213,12 @@
      * Queue transitions from empty to full when elements added
      */
     public void testEmptyFull() {
-        ArrayBlockingQueue q = new ArrayBlockingQueue(2);
+        BlockingQueue q = populatedQueue(0, 2, 2, false);
         assertTrue(q.isEmpty());
         assertEquals(2, q.remainingCapacity());
         q.add(one);
         assertFalse(q.isEmpty());
-        q.add(two);
+        assertTrue(q.offer(two));
         assertFalse(q.isEmpty());
         assertEquals(0, q.remainingCapacity());
         assertFalse(q.offer(three));
@@ -186,15 +228,18 @@
      * remainingCapacity decreases on add, increases on remove
      */
     public void testRemainingCapacity() {
-        BlockingQueue q = populatedQueue(SIZE);
-        for (int i = 0; i < SIZE; ++i) {
-            assertEquals(i, q.remainingCapacity());
-            assertEquals(SIZE, q.size() + q.remainingCapacity());
+        int size = ThreadLocalRandom.current().nextInt(1, SIZE);
+        BlockingQueue q = populatedQueue(size, size, 2 * size, false);
+        int spare = q.remainingCapacity();
+        int capacity = spare + size;
+        for (int i = 0; i < size; i++) {
+            assertEquals(spare + i, q.remainingCapacity());
+            assertEquals(capacity, q.size() + q.remainingCapacity());
             assertEquals(i, q.remove());
         }
-        for (int i = 0; i < SIZE; ++i) {
-            assertEquals(SIZE - i, q.remainingCapacity());
-            assertEquals(SIZE, q.size() + q.remainingCapacity());
+        for (int i = 0; i < size; i++) {
+            assertEquals(capacity - i, q.remainingCapacity());
+            assertEquals(capacity, q.size() + q.remainingCapacity());
             assertTrue(q.add(i));
         }
     }
@@ -213,12 +258,10 @@
      */
     public void testAdd() {
         ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
-        for (int i = 0; i < SIZE; ++i) {
-            assertTrue(q.add(new Integer(i)));
-        }
+        for (int i = 0; i < SIZE; i++) assertTrue(q.add((Integer) i));
         assertEquals(0, q.remainingCapacity());
         try {
-            q.add(new Integer(SIZE));
+            q.add((Integer) SIZE);
             shouldThrow();
         } catch (IllegalStateException success) {}
     }
@@ -252,13 +295,17 @@
     /**
      * addAll throws ISE if not enough room
      */
-    public void testAddAll4() {
-        ArrayBlockingQueue q = new ArrayBlockingQueue(1);
-        Integer[] ints = new Integer[SIZE];
-        for (int i = 0; i < SIZE; ++i)
-            ints[i] = new Integer(i);
+    public void testAddAll_insufficientSpace() {
+        int size = ThreadLocalRandom.current().nextInt(1, SIZE);
+        ArrayBlockingQueue q = populatedQueue(0, size, size, false);
+        // Just fits:
+        q.addAll(populatedQueue(size, size, 2 * size, false));
+        assertEquals(0, q.remainingCapacity());
+        assertEquals(size, q.size());
+        assertEquals(0, q.peek());
         try {
-            q.addAll(Arrays.asList(ints));
+            q = populatedQueue(0, size, size, false);
+            q.addAll(Collections.nCopies(size + 1, 42));
             shouldThrow();
         } catch (IllegalStateException success) {}
     }
@@ -545,8 +592,10 @@
      * contains(x) reports true when elements added but not yet removed
      */
     public void testContains() {
-        ArrayBlockingQueue q = populatedQueue(SIZE);
-        for (int i = 0; i < SIZE; ++i) {
+        int size = ThreadLocalRandom.current().nextInt(1, SIZE);
+        ArrayBlockingQueue q = populatedQueue(size, size, 2 * size, false);
+        assertFalse(q.contains(null));
+        for (int i = 0; i < size; ++i) {
             assertTrue(q.contains(new Integer(i)));
             assertEquals(i, q.poll());
             assertFalse(q.contains(new Integer(i)));
@@ -557,11 +606,13 @@
      * clear removes all elements
      */
     public void testClear() {
-        ArrayBlockingQueue q = populatedQueue(SIZE);
+        int size = ThreadLocalRandom.current().nextInt(1, 5);
+        ArrayBlockingQueue q = populatedQueue(size, size, 2 * size, false);
+        int capacity = size + q.remainingCapacity();
         q.clear();
         assertTrue(q.isEmpty());
         assertEquals(0, q.size());
-        assertEquals(SIZE, q.remainingCapacity());
+        assertEquals(capacity, q.remainingCapacity());
         q.add(one);
         assertFalse(q.isEmpty());
         assertTrue(q.contains(one));
@@ -618,103 +669,75 @@
         }
     }
 
-    void checkToArray(ArrayBlockingQueue q) {
+    void checkToArray(ArrayBlockingQueue<Integer> q) {
         int size = q.size();
-        Object[] o = q.toArray();
-        assertEquals(size, o.length);
+        Object[] a1 = q.toArray();
+        assertEquals(size, a1.length);
+        Integer[] a2 = q.toArray(new Integer[0]);
+        assertEquals(size, a2.length);
+        Integer[] a3 = q.toArray(new Integer[Math.max(0, size - 1)]);
+        assertEquals(size, a3.length);
+        Integer[] a4 = new Integer[size];
+        assertSame(a4, q.toArray(a4));
+        Integer[] a5 = new Integer[size + 1];
+        Arrays.fill(a5, 42);
+        assertSame(a5, q.toArray(a5));
+        Integer[] a6 = new Integer[size + 2];
+        Arrays.fill(a6, 42);
+        assertSame(a6, q.toArray(a6));
+        Object[][] as = { a1, a2, a3, a4, a5, a6 };
+        for (Object[] a : as) {
+            if (a.length > size) assertNull(a[size]);
+            if (a.length > size + 1) assertEquals(42, a[size + 1]);
+        }
         Iterator it = q.iterator();
+        Integer s = q.peek();
         for (int i = 0; i < size; i++) {
             Integer x = (Integer) it.next();
-            assertEquals((Integer)o[0] + i, (int) x);
-            assertSame(o[i], x);
+            assertEquals(s + i, (int) x);
+            for (Object[] a : as)
+                assertSame(a1[i], x);
         }
     }
 
     /**
-     * toArray() contains all elements in FIFO order
+     * toArray() and toArray(a) contain all elements in FIFO order
      */
     public void testToArray() {
-        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray(q);
-            q.add(i);
-        }
-        // Provoke wraparound
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray(q);
-            assertEquals(i, q.poll());
-            checkToArray(q);
-            q.add(SIZE + i);
-        }
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray(q);
-            assertEquals(SIZE + i, q.poll());
-        }
-    }
-
-    void checkToArray2(ArrayBlockingQueue q) {
-        int size = q.size();
-        Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
-        Integer[] a2 = new Integer[size];
-        Integer[] a3 = new Integer[size + 2];
-        if (size > 0) Arrays.fill(a1, 42);
-        Arrays.fill(a2, 42);
-        Arrays.fill(a3, 42);
-        Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
-        Integer[] b2 = (Integer[]) q.toArray(a2);
-        Integer[] b3 = (Integer[]) q.toArray(a3);
-        assertSame(a2, b2);
-        assertSame(a3, b3);
-        Iterator it = q.iterator();
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        final int size = rnd.nextInt(6);
+        final int capacity = Math.max(1, size + rnd.nextInt(size + 1));
+        ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<>(capacity);
         for (int i = 0; i < size; i++) {
-            Integer x = (Integer) it.next();
-            assertSame(b1[i], x);
-            assertEquals(b1[0] + i, (int) x);
-            assertSame(b2[i], x);
-            assertSame(b3[i], x);
-        }
-        assertNull(a3[size]);
-        assertEquals(42, (int) a3[size + 1]);
-        if (size > 0) {
-            assertNotSame(a1, b1);
-            assertEquals(size, b1.length);
-            for (int i = 0; i < a1.length; i++) {
-                assertEquals(42, (int) a1[i]);
-            }
-        }
-    }
-
-    /**
-     * toArray(a) contains all elements in FIFO order
-     */
-    public void testToArray2() {
-        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray2(q);
+            checkToArray(q);
             q.add(i);
         }
         // Provoke wraparound
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray2(q);
-            assertEquals(i, q.poll());
-            checkToArray2(q);
-            q.add(SIZE + i);
+        int added = size * 2;
+        for (int i = 0; i < added; i++) {
+            checkToArray(q);
+            assertEquals((Integer) i, q.poll());
+            q.add(size + i);
         }
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray2(q);
-            assertEquals(SIZE + i, q.poll());
+        for (int i = 0; i < size; i++) {
+            checkToArray(q);
+            assertEquals((Integer) (added + i), q.poll());
         }
     }
 
     /**
      * toArray(incompatible array type) throws ArrayStoreException
      */
-    public void testToArray1_BadArg() {
+    public void testToArray_incompatibleArrayType() {
         ArrayBlockingQueue q = populatedQueue(SIZE);
         try {
             q.toArray(new String[10]);
             shouldThrow();
         } catch (ArrayStoreException success) {}
+        try {
+            q.toArray(new String[0]);
+            shouldThrow();
+        } catch (ArrayStoreException success) {}
     }
 
     /**
@@ -943,8 +966,8 @@
      */
     public void testNeverContainsNull() {
         Collection<?>[] qs = {
-            new ArrayBlockingQueue<Object>(10),
-            populatedQueue(2),
+            populatedQueue(0, 1, 10, false),
+            populatedQueue(2, 2, 10, true),
         };
 
         for (Collection<?> q : qs) {
diff --git a/jdk/test/java/util/concurrent/tck/ArrayDeque8Test.java b/jdk/test/java/util/concurrent/tck/ArrayDeque8Test.java
new file mode 100644
index 0000000..0a7f26b
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/ArrayDeque8Test.java
@@ -0,0 +1,125 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.ArrayDeque;
+import java.util.Collections;
+import java.util.Spliterator;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class ArrayDeque8Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        return newTestSuite(ArrayDeque8Test.class);
+    }
+
+    /**
+     * Spliterator.getComparator always throws IllegalStateException
+     */
+    public void testSpliterator_getComparator() {
+        assertThrows(IllegalStateException.class,
+                     () -> new ArrayDeque().spliterator().getComparator());
+    }
+
+    /**
+     * Spliterator characteristics are as advertised
+     */
+    public void testSpliterator_characteristics() {
+        ArrayDeque q = new ArrayDeque();
+        Spliterator s = q.spliterator();
+        int characteristics = s.characteristics();
+        int required = Spliterator.NONNULL
+            | Spliterator.ORDERED
+            | Spliterator.SIZED
+            | Spliterator.SUBSIZED;
+        assertEquals(required, characteristics & required);
+        assertTrue(s.hasCharacteristics(required));
+        assertEquals(0, characteristics
+                     & (Spliterator.CONCURRENT
+                        | Spliterator.DISTINCT
+                        | Spliterator.IMMUTABLE
+                        | Spliterator.SORTED));
+    }
+
+    /**
+     * Handle capacities near Integer.MAX_VALUE.
+     * ant -Dvmoptions='-Xms28g -Xmx28g' -Djsr166.expensiveTests=true -Djsr166.tckTestClass=ArrayDeque8Test -Djsr166.methodFilter=testHugeCapacity tck
+     */
+    public void testHugeCapacity() {
+        if (! (testImplementationDetails
+               && expensiveTests
+               && Runtime.getRuntime().maxMemory() > 24L * (1 << 30)))
+            return;
+
+        final Integer e = 42;
+        final int maxArraySize = Integer.MAX_VALUE - 8;
+
+        assertThrows(OutOfMemoryError.class,
+                     () -> new ArrayDeque(Integer.MAX_VALUE));
+
+        {
+            ArrayDeque q = new ArrayDeque(maxArraySize - 1);
+            assertEquals(0, q.size());
+            assertTrue(q.isEmpty());
+            q = null;
+        }
+
+        {
+            ArrayDeque q = new ArrayDeque();
+            assertTrue(q.addAll(Collections.nCopies(maxArraySize - 3, e)));
+            assertEquals(e, q.peekFirst());
+            assertEquals(e, q.peekLast());
+            assertEquals(maxArraySize - 3, q.size());
+            q.addFirst((Integer) 0);
+            q.addLast((Integer) 1);
+            assertEquals((Integer) 0, q.peekFirst());
+            assertEquals((Integer) 1, q.peekLast());
+            assertEquals(maxArraySize - 1, q.size());
+
+            ArrayDeque qq = q;
+            ArrayDeque smallish = new ArrayDeque(
+                Collections.nCopies(Integer.MAX_VALUE - q.size() + 1, e));
+            assertThrows(
+                IllegalStateException.class,
+                () -> qq.addAll(qq),
+                () -> qq.addAll(smallish),
+                () -> smallish.addAll(qq));
+        }
+    }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java b/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java
index 4241f59..1bbd981 100644
--- a/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java
+++ b/jdk/test/java/util/concurrent/tck/ArrayDequeTest.java
@@ -26,19 +26,22 @@
  * However, the following notice accompanied the original version of this
  * file:
  *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 import java.util.ArrayDeque;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Queue;
 import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -49,20 +52,60 @@
     }
 
     public static Test suite() {
-        return new TestSuite(ArrayDequeTest.class);
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return ArrayDeque.class; }
+            public Collection emptyCollection() { return populatedDeque(0); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return false; }
+            public boolean permitsNulls() { return false; }
+        }
+        return newTestSuite(ArrayDequeTest.class,
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /**
      * Returns a new deque of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
-    private ArrayDeque<Integer> populatedDeque(int n) {
-        ArrayDeque<Integer> q = new ArrayDeque<Integer>();
+    private static ArrayDeque<Integer> populatedDeque(int n) {
+        // Randomize various aspects of memory layout, including
+        // capacity slop and wraparound.
+        final ArrayDeque<Integer> q;
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        switch (rnd.nextInt(6)) {
+        case 0: q = new ArrayDeque<Integer>();      break;
+        case 1: q = new ArrayDeque<Integer>(0);     break;
+        case 2: q = new ArrayDeque<Integer>(1);     break;
+        case 3: q = new ArrayDeque<Integer>(Math.max(0, n - 1)); break;
+        case 4: q = new ArrayDeque<Integer>(n);     break;
+        case 5: q = new ArrayDeque<Integer>(n + 1); break;
+        default: throw new AssertionError();
+        }
+        switch (rnd.nextInt(3)) {
+        case 0:
+            q.addFirst(42);
+            assertEquals((Integer) 42, q.removeLast());
+            break;
+        case 1:
+            q.addLast(42);
+            assertEquals((Integer) 42, q.removeFirst());
+            break;
+        case 2: /* do nothing */ break;
+        default: throw new AssertionError();
+        }
         assertTrue(q.isEmpty());
-        for (int i = 0; i < n; ++i)
-            assertTrue(q.offerLast(new Integer(i)));
-        assertFalse(q.isEmpty());
+        if (rnd.nextBoolean())
+            for (int i = 0; i < n; i++)
+                assertTrue(q.offerLast((Integer) i));
+        else
+            for (int i = n; --i >= 0; )
+                q.addFirst((Integer) i);
         assertEquals(n, q.size());
+        if (n > 0) {
+            assertFalse(q.isEmpty());
+            assertEquals((Integer) 0, q.peekFirst());
+            assertEquals((Integer) (n - 1), q.peekLast());
+        }
         return q;
     }
 
@@ -556,30 +599,48 @@
      * removeFirstOccurrence(x) removes x and returns true if present
      */
     public void testRemoveFirstOccurrence() {
-        ArrayDeque q = populatedDeque(SIZE);
+        Deque<Integer> q = populatedDeque(SIZE);
+        assertFalse(q.removeFirstOccurrence(null));
         for (int i = 1; i < SIZE; i += 2) {
-            assertTrue(q.removeFirstOccurrence(new Integer(i)));
+            assertTrue(q.removeFirstOccurrence(i));
+            assertFalse(q.contains(i));
         }
         for (int i = 0; i < SIZE; i += 2) {
-            assertTrue(q.removeFirstOccurrence(new Integer(i)));
-            assertFalse(q.removeFirstOccurrence(new Integer(i + 1)));
+            assertTrue(q.removeFirstOccurrence(i));
+            assertFalse(q.removeFirstOccurrence(i + 1));
+            assertFalse(q.contains(i));
+            assertFalse(q.contains(i + 1));
         }
         assertTrue(q.isEmpty());
+        assertFalse(q.removeFirstOccurrence(null));
+        assertFalse(q.removeFirstOccurrence(42));
+        q = new ArrayDeque();
+        assertFalse(q.removeFirstOccurrence(null));
+        assertFalse(q.removeFirstOccurrence(42));
     }
 
     /**
      * removeLastOccurrence(x) removes x and returns true if present
      */
     public void testRemoveLastOccurrence() {
-        ArrayDeque q = populatedDeque(SIZE);
+        Deque<Integer> q = populatedDeque(SIZE);
+        assertFalse(q.removeLastOccurrence(null));
         for (int i = 1; i < SIZE; i += 2) {
-            assertTrue(q.removeLastOccurrence(new Integer(i)));
+            assertTrue(q.removeLastOccurrence(i));
+            assertFalse(q.contains(i));
         }
         for (int i = 0; i < SIZE; i += 2) {
-            assertTrue(q.removeLastOccurrence(new Integer(i)));
-            assertFalse(q.removeLastOccurrence(new Integer(i + 1)));
+            assertTrue(q.removeLastOccurrence(i));
+            assertFalse(q.removeLastOccurrence(i + 1));
+            assertFalse(q.contains(i));
+            assertFalse(q.contains(i + 1));
         }
         assertTrue(q.isEmpty());
+        assertFalse(q.removeLastOccurrence(null));
+        assertFalse(q.removeLastOccurrence(42));
+        q = new ArrayDeque();
+        assertFalse(q.removeLastOccurrence(null));
+        assertFalse(q.removeLastOccurrence(42));
     }
 
     /**
@@ -652,89 +713,57 @@
         }
     }
 
-    void checkToArray(ArrayDeque q) {
+    void checkToArray(ArrayDeque<Integer> q) {
         int size = q.size();
-        Object[] o = q.toArray();
-        assertEquals(size, o.length);
+        Object[] a1 = q.toArray();
+        assertEquals(size, a1.length);
+        Integer[] a2 = q.toArray(new Integer[0]);
+        assertEquals(size, a2.length);
+        Integer[] a3 = q.toArray(new Integer[Math.max(0, size - 1)]);
+        assertEquals(size, a3.length);
+        Integer[] a4 = new Integer[size];
+        assertSame(a4, q.toArray(a4));
+        Integer[] a5 = new Integer[size + 1];
+        Arrays.fill(a5, 42);
+        assertSame(a5, q.toArray(a5));
+        Integer[] a6 = new Integer[size + 2];
+        Arrays.fill(a6, 42);
+        assertSame(a6, q.toArray(a6));
+        Object[][] as = { a1, a2, a3, a4, a5, a6 };
+        for (Object[] a : as) {
+            if (a.length > size) assertNull(a[size]);
+            if (a.length > size + 1) assertEquals(42, a[size + 1]);
+        }
         Iterator it = q.iterator();
+        Integer s = q.peekFirst();
         for (int i = 0; i < size; i++) {
             Integer x = (Integer) it.next();
-            assertEquals((Integer)o[0] + i, (int) x);
-            assertSame(o[i], x);
+            assertEquals(s + i, (int) x);
+            for (Object[] a : as)
+                assertSame(a1[i], x);
         }
     }
 
     /**
-     * toArray() contains all elements in FIFO order
+     * toArray() and toArray(a) contain all elements in FIFO order
      */
     public void testToArray() {
-        ArrayDeque q = new ArrayDeque();
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray(q);
-            q.addLast(i);
-        }
-        // Provoke wraparound
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray(q);
-            assertEquals(i, q.poll());
-            q.addLast(SIZE + i);
-        }
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray(q);
-            assertEquals(SIZE + i, q.poll());
-        }
-    }
-
-    void checkToArray2(ArrayDeque q) {
-        int size = q.size();
-        Integer[] a1 = (size == 0) ? null : new Integer[size - 1];
-        Integer[] a2 = new Integer[size];
-        Integer[] a3 = new Integer[size + 2];
-        if (size > 0) Arrays.fill(a1, 42);
-        Arrays.fill(a2, 42);
-        Arrays.fill(a3, 42);
-        Integer[] b1 = (size == 0) ? null : (Integer[]) q.toArray(a1);
-        Integer[] b2 = (Integer[]) q.toArray(a2);
-        Integer[] b3 = (Integer[]) q.toArray(a3);
-        assertSame(a2, b2);
-        assertSame(a3, b3);
-        Iterator it = q.iterator();
+        final int size = ThreadLocalRandom.current().nextInt(10);
+        ArrayDeque<Integer> q = new ArrayDeque<>(size);
         for (int i = 0; i < size; i++) {
-            Integer x = (Integer) it.next();
-            assertSame(b1[i], x);
-            assertEquals(b1[0] + i, (int) x);
-            assertSame(b2[i], x);
-            assertSame(b3[i], x);
-        }
-        assertNull(a3[size]);
-        assertEquals(42, (int) a3[size + 1]);
-        if (size > 0) {
-            assertNotSame(a1, b1);
-            assertEquals(size, b1.length);
-            for (int i = 0; i < a1.length; i++) {
-                assertEquals(42, (int) a1[i]);
-            }
-        }
-    }
-
-    /**
-     * toArray(a) contains all elements in FIFO order
-     */
-    public void testToArray2() {
-        ArrayDeque q = new ArrayDeque();
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray2(q);
+            checkToArray(q);
             q.addLast(i);
         }
         // Provoke wraparound
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray2(q);
-            assertEquals(i, q.poll());
-            q.addLast(SIZE + i);
+        int added = size * 2;
+        for (int i = 0; i < added; i++) {
+            checkToArray(q);
+            assertEquals((Integer) i, q.poll());
+            q.addLast(size + i);
         }
-        for (int i = 0; i < SIZE; i++) {
-            checkToArray2(q);
-            assertEquals(SIZE + i, q.poll());
+        for (int i = 0; i < size; i++) {
+            checkToArray(q);
+            assertEquals((Integer) (added + i), q.poll());
         }
     }
 
@@ -753,13 +782,17 @@
     /**
      * toArray(incompatible array type) throws ArrayStoreException
      */
-    public void testToArray1_BadArg() {
+    public void testToArray_incompatibleArrayType() {
         ArrayDeque l = new ArrayDeque();
         l.add(new Integer(5));
         try {
             l.toArray(new String[10]);
             shouldThrow();
         } catch (ArrayStoreException success) {}
+        try {
+            l.toArray(new String[0]);
+            shouldThrow();
+        } catch (ArrayStoreException success) {}
     }
 
     /**
@@ -917,6 +950,25 @@
         assertNotSame(y, x);
         assertEquals(x.size(), y.size());
         assertEquals(x.toString(), y.toString());
+        assertEquals(Arrays.toString(x.toArray()), Arrays.toString(y.toArray()));
+        assertTrue(Arrays.equals(x.toArray(), y.toArray()));
+        while (!x.isEmpty()) {
+            assertFalse(y.isEmpty());
+            assertEquals(x.remove(), y.remove());
+        }
+        assertTrue(y.isEmpty());
+    }
+
+    /**
+     * A cloned deque has same elements in same order
+     */
+    public void testClone() throws Exception {
+        ArrayDeque<Integer> x = populatedDeque(SIZE);
+        ArrayDeque<Integer> y = x.clone();
+
+        assertNotSame(y, x);
+        assertEquals(x.size(), y.size());
+        assertEquals(x.toString(), y.toString());
         assertTrue(Arrays.equals(x.toArray(), y.toArray()));
         while (!x.isEmpty()) {
             assertFalse(y.isEmpty());
diff --git a/jdk/test/java/util/concurrent/tck/ArrayListTest.java b/jdk/test/java/util/concurrent/tck/ArrayListTest.java
new file mode 100644
index 0000000..193b4af
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/ArrayListTest.java
@@ -0,0 +1,66 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class ArrayListTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return ArrayList.class; }
+            public List emptyCollection() { return new ArrayList(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return false; }
+            public boolean permitsNulls() { return true; }
+        }
+        class SubListImplementation extends Implementation {
+            public List emptyCollection() {
+                return super.emptyCollection().subList(0, 0);
+            }
+        }
+        return newTestSuite(
+                // ArrayListTest.class,
+                CollectionTest.testSuite(new Implementation()),
+                CollectionTest.testSuite(new SubListImplementation()));
+    }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/Atomic8Test.java b/jdk/test/java/util/concurrent/tck/Atomic8Test.java
index 721f502..c4a4394 100644
--- a/jdk/test/java/util/concurrent/tck/Atomic8Test.java
+++ b/jdk/test/java/util/concurrent/tck/Atomic8Test.java
@@ -45,6 +45,9 @@
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
+/**
+ * Tests of atomic class methods accepting lambdas introduced in JDK8.
+ */
 public class Atomic8Test extends JSR166TestCase {
 
     public static void main(String[] args) {
@@ -54,30 +57,25 @@
         return new TestSuite(Atomic8Test.class);
     }
 
-    /*
-     * Tests of atomic class methods accepting lambdas
-     * introduced in JDK8.
-     */
-
     static long addLong17(long x) { return x + 17; }
     static int addInt17(int x) { return x + 17; }
     static Integer addInteger17(Integer x) {
-        return new Integer(x.intValue() + 17);
+        return x.intValue() + 17;
     }
     static Integer sumInteger(Integer x, Integer y) {
-        return new Integer(x.intValue() + y.intValue());
+        return x.intValue() + y.intValue();
     }
 
     volatile long aLongField;
     volatile int anIntField;
     volatile Integer anIntegerField;
 
-    AtomicLongFieldUpdater aLongFieldUpdater() {
+    AtomicLongFieldUpdater<Atomic8Test> aLongFieldUpdater() {
         return AtomicLongFieldUpdater.newUpdater
             (Atomic8Test.class, "aLongField");
     }
 
-    AtomicIntegerFieldUpdater anIntFieldUpdater() {
+    AtomicIntegerFieldUpdater<Atomic8Test> anIntFieldUpdater() {
         return AtomicIntegerFieldUpdater.newUpdater
             (Atomic8Test.class, "anIntField");
     }
@@ -180,9 +178,9 @@
      */
     public void testReferenceGetAndUpdate() {
         AtomicReference<Integer> a = new AtomicReference<>(one);
-        assertEquals(new Integer(1), a.getAndUpdate(Atomic8Test::addInteger17));
-        assertEquals(new Integer(18), a.getAndUpdate(Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get());
+        assertEquals((Integer) 1, a.getAndUpdate(Atomic8Test::addInteger17));
+        assertEquals((Integer) 18, a.getAndUpdate(Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.get());
     }
 
     /**
@@ -191,9 +189,9 @@
      */
     public void testReferenceUpdateAndGet() {
         AtomicReference<Integer> a = new AtomicReference<>(one);
-        assertEquals(new Integer(18), a.updateAndGet(Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.updateAndGet(Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get());
+        assertEquals((Integer) 18, a.updateAndGet(Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.updateAndGet(Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.get());
     }
 
     /**
@@ -202,9 +200,9 @@
      */
     public void testReferenceGetAndAccumulate() {
         AtomicReference<Integer> a = new AtomicReference<>(one);
-        assertEquals(new Integer(1), a.getAndAccumulate(2, Atomic8Test::sumInteger));
-        assertEquals(new Integer(3), a.getAndAccumulate(3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(6), a.get());
+        assertEquals((Integer) 1, a.getAndAccumulate(2, Atomic8Test::sumInteger));
+        assertEquals((Integer) 3, a.getAndAccumulate(3, Atomic8Test::sumInteger));
+        assertEquals((Integer) 6, a.get());
     }
 
     /**
@@ -213,9 +211,9 @@
      */
     public void testReferenceAccumulateAndGet() {
         AtomicReference<Integer> a = new AtomicReference<>(one);
-        assertEquals(new Integer(7), a.accumulateAndGet(6, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.accumulateAndGet(3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.get());
+        assertEquals((Integer) 7, a.accumulateAndGet(6, Atomic8Test::sumInteger));
+        assertEquals((Integer) 10, a.accumulateAndGet(3, Atomic8Test::sumInteger));
+        assertEquals((Integer) 10, a.get());
     }
 
     /**
@@ -320,9 +318,9 @@
     public void testReferenceArrayGetAndUpdate() {
         AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
         a.set(0, one);
-        assertEquals(new Integer(1), a.getAndUpdate(0, Atomic8Test::addInteger17));
-        assertEquals(new Integer(18), a.getAndUpdate(0, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get(0));
+        assertEquals((Integer) 1, a.getAndUpdate(0, Atomic8Test::addInteger17));
+        assertEquals((Integer) 18, a.getAndUpdate(0, Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.get(0));
     }
 
     /**
@@ -332,8 +330,8 @@
     public void testReferenceArrayUpdateAndGet() {
         AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
         a.set(0, one);
-        assertEquals(new Integer(18), a.updateAndGet(0, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.updateAndGet(0, Atomic8Test::addInteger17));
+        assertEquals((Integer) 18, a.updateAndGet(0, Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.updateAndGet(0, Atomic8Test::addInteger17));
     }
 
     /**
@@ -343,9 +341,9 @@
     public void testReferenceArrayGetAndAccumulate() {
         AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
         a.set(0, one);
-        assertEquals(new Integer(1), a.getAndAccumulate(0, 2, Atomic8Test::sumInteger));
-        assertEquals(new Integer(3), a.getAndAccumulate(0, 3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(6), a.get(0));
+        assertEquals((Integer) 1, a.getAndAccumulate(0, 2, Atomic8Test::sumInteger));
+        assertEquals((Integer) 3, a.getAndAccumulate(0, 3, Atomic8Test::sumInteger));
+        assertEquals((Integer) 6, a.get(0));
     }
 
     /**
@@ -355,8 +353,8 @@
     public void testReferenceArrayAccumulateAndGet() {
         AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
         a.set(0, one);
-        assertEquals(new Integer(7), a.accumulateAndGet(0, 6, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.accumulateAndGet(0, 3, Atomic8Test::sumInteger));
+        assertEquals((Integer) 7, a.accumulateAndGet(0, 6, Atomic8Test::sumInteger));
+        assertEquals((Integer) 10, a.accumulateAndGet(0, 3, Atomic8Test::sumInteger));
     }
 
     /**
@@ -470,10 +468,10 @@
     public void testReferenceFieldUpdaterGetAndUpdate() {
         AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
         a.set(this, one);
-        assertEquals(new Integer(1), a.getAndUpdate(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(18), a.getAndUpdate(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get(this));
-        assertEquals(new Integer(35), anIntegerField);
+        assertEquals((Integer) 1, a.getAndUpdate(this, Atomic8Test::addInteger17));
+        assertEquals((Integer) 18, a.getAndUpdate(this, Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.get(this));
+        assertEquals((Integer) 35, anIntegerField);
     }
 
     /**
@@ -483,10 +481,10 @@
     public void testReferenceFieldUpdaterUpdateAndGet() {
         AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
         a.set(this, one);
-        assertEquals(new Integer(18), a.updateAndGet(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.updateAndGet(this, Atomic8Test::addInteger17));
-        assertEquals(new Integer(35), a.get(this));
-        assertEquals(new Integer(35), anIntegerField);
+        assertEquals((Integer) 18, a.updateAndGet(this, Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.updateAndGet(this, Atomic8Test::addInteger17));
+        assertEquals((Integer) 35, a.get(this));
+        assertEquals((Integer) 35, anIntegerField);
     }
 
     /**
@@ -496,10 +494,10 @@
     public void testReferenceFieldUpdaterGetAndAccumulate() {
         AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
         a.set(this, one);
-        assertEquals(new Integer(1), a.getAndAccumulate(this, 2, Atomic8Test::sumInteger));
-        assertEquals(new Integer(3), a.getAndAccumulate(this, 3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(6), a.get(this));
-        assertEquals(new Integer(6), anIntegerField);
+        assertEquals((Integer) 1, a.getAndAccumulate(this, 2, Atomic8Test::sumInteger));
+        assertEquals((Integer) 3, a.getAndAccumulate(this, 3, Atomic8Test::sumInteger));
+        assertEquals((Integer) 6, a.get(this));
+        assertEquals((Integer) 6, anIntegerField);
     }
 
     /**
@@ -509,10 +507,10 @@
     public void testReferenceFieldUpdaterAccumulateAndGet() {
         AtomicReferenceFieldUpdater<Atomic8Test,Integer> a = anIntegerFieldUpdater();
         a.set(this, one);
-        assertEquals(new Integer(7), a.accumulateAndGet(this, 6, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.accumulateAndGet(this, 3, Atomic8Test::sumInteger));
-        assertEquals(new Integer(10), a.get(this));
-        assertEquals(new Integer(10), anIntegerField);
+        assertEquals((Integer) 7, a.accumulateAndGet(this, 6, Atomic8Test::sumInteger));
+        assertEquals((Integer) 10, a.accumulateAndGet(this, 3, Atomic8Test::sumInteger));
+        assertEquals((Integer) 10, a.get(this));
+        assertEquals((Integer) 10, anIntegerField);
     }
 
     /**
@@ -530,9 +528,6 @@
             () -> aLongFieldUpdater().getAndUpdate(this, null),
             () -> anIntFieldUpdater().getAndUpdate(this, null),
             () -> anIntegerFieldUpdater().getAndUpdate(this, null),
-            ////() -> aLongFieldUpdater().getAndUpdate(null, Atomic8Test::addLong17),
-            ////() -> anIntFieldUpdater().getAndUpdate(null, Atomic8Test::addInt17),
-            ////() -> anIntegerFieldUpdater().getAndUpdate(null, Atomic8Test::addInteger17),
         };
         assertThrows(NullPointerException.class, throwingActions);
     }
@@ -593,4 +588,40 @@
         assertThrows(NullPointerException.class, throwingActions);
     }
 
+    /**
+     * Object arguments for parameters of type T that are not
+     * instances of the class passed to the newUpdater call will
+     * result in a ClassCastException being thrown.
+     */
+    public void testFieldUpdaters_ClassCastException() {
+        // Use raw types to allow passing wrong object type, provoking CCE
+        final AtomicLongFieldUpdater longUpdater = aLongFieldUpdater();
+        final AtomicIntegerFieldUpdater intUpdater = anIntFieldUpdater();
+        final AtomicReferenceFieldUpdater refUpdater = anIntegerFieldUpdater();
+        final Object obj = new Object();
+        for (Object x : new Object[]{ new Object(), null }) {
+            Runnable[] throwingActions = {
+                () -> longUpdater.get(x),
+                () -> intUpdater.get(x),
+                () -> refUpdater.get(x),
+
+                () -> longUpdater.set(x, 17L),
+                () -> intUpdater.set(x, 17),
+                () -> refUpdater.set(x, (Integer) 17),
+
+                () -> longUpdater.addAndGet(x, 17L),
+                () -> intUpdater.addAndGet(x, 17),
+
+                () -> longUpdater.getAndUpdate(x, y -> y),
+                () -> intUpdater.getAndUpdate(x, y -> y),
+                () -> refUpdater.getAndUpdate(x, y -> y),
+
+                () -> longUpdater.compareAndSet(x, 17L, 42L),
+                () -> intUpdater.compareAndSet(x, 17, 42),
+                () -> refUpdater.compareAndSet(x, (Integer) 17, (Integer) 42),
+            };
+            assertThrows(ClassCastException.class, throwingActions);
+        }
+    }
+
 }
diff --git a/jdk/test/java/util/concurrent/tck/Collection8Test.java b/jdk/test/java/util/concurrent/tck/Collection8Test.java
index 36f99e1..8d7e48c 100644
--- a/jdk/test/java/util/concurrent/tck/Collection8Test.java
+++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java
@@ -32,18 +32,35 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+import static java.util.concurrent.TimeUnit.HOURS;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Spliterator;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 import junit.framework.Test;
 
@@ -66,16 +83,422 @@
                                       impl);
     }
 
+    Object bomb() {
+        return new Object() {
+                public boolean equals(Object x) { throw new AssertionError(); }
+                public int hashCode() { throw new AssertionError(); }
+            };
+    }
+
+    /** Checks properties of empty collections. */
+    public void testEmptyMeansEmpty() throws Throwable {
+        Collection c = impl.emptyCollection();
+        emptyMeansEmpty(c);
+
+        if (c instanceof java.io.Serializable) {
+            try {
+                emptyMeansEmpty(serialClonePossiblyFailing(c));
+            } catch (java.io.NotSerializableException ex) {
+                // excusable when we have a serializable wrapper around
+                // a non-serializable collection, as can happen with:
+                // Vector.subList() => wrapped AbstractList$RandomAccessSubList
+                if (testImplementationDetails
+                    && (! c.getClass().getName().matches(
+                                "java.util.Collections.*")))
+                    throw ex;
+            }
+        }
+
+        Collection clone = cloneableClone(c);
+        if (clone != null)
+            emptyMeansEmpty(clone);
+    }
+
+    void emptyMeansEmpty(Collection c) throws InterruptedException {
+        assertTrue(c.isEmpty());
+        assertEquals(0, c.size());
+        assertEquals("[]", c.toString());
+        {
+            Object[] a = c.toArray();
+            assertEquals(0, a.length);
+            assertSame(Object[].class, a.getClass());
+        }
+        {
+            Object[] a = new Object[0];
+            assertSame(a, c.toArray(a));
+        }
+        {
+            Integer[] a = new Integer[0];
+            assertSame(a, c.toArray(a));
+        }
+        {
+            Integer[] a = { 1, 2, 3};
+            assertSame(a, c.toArray(a));
+            assertNull(a[0]);
+            assertSame(2, a[1]);
+            assertSame(3, a[2]);
+        }
+        assertIteratorExhausted(c.iterator());
+        Consumer alwaysThrows = e -> { throw new AssertionError(); };
+        c.forEach(alwaysThrows);
+        c.iterator().forEachRemaining(alwaysThrows);
+        c.spliterator().forEachRemaining(alwaysThrows);
+        assertFalse(c.spliterator().tryAdvance(alwaysThrows));
+        if (c.spliterator().hasCharacteristics(Spliterator.SIZED))
+            assertEquals(0, c.spliterator().estimateSize());
+        assertFalse(c.contains(bomb()));
+        assertFalse(c.remove(bomb()));
+        if (c instanceof Queue) {
+            Queue q = (Queue) c;
+            assertNull(q.peek());
+            assertNull(q.poll());
+        }
+        if (c instanceof Deque) {
+            Deque d = (Deque) c;
+            assertNull(d.peekFirst());
+            assertNull(d.peekLast());
+            assertNull(d.pollFirst());
+            assertNull(d.pollLast());
+            assertIteratorExhausted(d.descendingIterator());
+            d.descendingIterator().forEachRemaining(alwaysThrows);
+            assertFalse(d.removeFirstOccurrence(bomb()));
+            assertFalse(d.removeLastOccurrence(bomb()));
+        }
+        if (c instanceof BlockingQueue) {
+            BlockingQueue q = (BlockingQueue) c;
+            assertNull(q.poll(0L, MILLISECONDS));
+        }
+        if (c instanceof BlockingDeque) {
+            BlockingDeque q = (BlockingDeque) c;
+            assertNull(q.pollFirst(0L, MILLISECONDS));
+            assertNull(q.pollLast(0L, MILLISECONDS));
+        }
+    }
+
+    public void testNullPointerExceptions() throws InterruptedException {
+        Collection c = impl.emptyCollection();
+        assertThrows(
+            NullPointerException.class,
+            () -> c.addAll(null),
+            () -> c.containsAll(null),
+            () -> c.retainAll(null),
+            () -> c.removeAll(null),
+            () -> c.removeIf(null),
+            () -> c.forEach(null),
+            () -> c.iterator().forEachRemaining(null),
+            () -> c.spliterator().forEachRemaining(null),
+            () -> c.spliterator().tryAdvance(null),
+            () -> c.toArray(null));
+
+        if (!impl.permitsNulls()) {
+            assertThrows(
+                NullPointerException.class,
+                () -> c.add(null));
+        }
+        if (!impl.permitsNulls() && c instanceof Queue) {
+            Queue q = (Queue) c;
+            assertThrows(
+                NullPointerException.class,
+                () -> q.offer(null));
+        }
+        if (!impl.permitsNulls() && c instanceof Deque) {
+            Deque d = (Deque) c;
+            assertThrows(
+                NullPointerException.class,
+                () -> d.addFirst(null),
+                () -> d.addLast(null),
+                () -> d.offerFirst(null),
+                () -> d.offerLast(null),
+                () -> d.push(null),
+                () -> d.descendingIterator().forEachRemaining(null));
+        }
+        if (c instanceof BlockingQueue) {
+            BlockingQueue q = (BlockingQueue) c;
+            assertThrows(
+                NullPointerException.class,
+                () -> {
+                    try { q.offer(null, 1L, HOURS); }
+                    catch (InterruptedException ex) {
+                        throw new AssertionError(ex);
+                    }},
+                () -> {
+                    try { q.put(null); }
+                    catch (InterruptedException ex) {
+                        throw new AssertionError(ex);
+                    }});
+        }
+        if (c instanceof BlockingDeque) {
+            BlockingDeque q = (BlockingDeque) c;
+            assertThrows(
+                NullPointerException.class,
+                () -> {
+                    try { q.offerFirst(null, 1L, HOURS); }
+                    catch (InterruptedException ex) {
+                        throw new AssertionError(ex);
+                    }},
+                () -> {
+                    try { q.offerLast(null, 1L, HOURS); }
+                    catch (InterruptedException ex) {
+                        throw new AssertionError(ex);
+                    }},
+                () -> {
+                    try { q.putFirst(null); }
+                    catch (InterruptedException ex) {
+                        throw new AssertionError(ex);
+                    }},
+                () -> {
+                    try { q.putLast(null); }
+                    catch (InterruptedException ex) {
+                        throw new AssertionError(ex);
+                    }});
+        }
+    }
+
+    public void testNoSuchElementExceptions() {
+        Collection c = impl.emptyCollection();
+        assertThrows(
+            NoSuchElementException.class,
+            () -> c.iterator().next());
+
+        if (c instanceof Queue) {
+            Queue q = (Queue) c;
+            assertThrows(
+                NoSuchElementException.class,
+                () -> q.element(),
+                () -> q.remove());
+        }
+        if (c instanceof Deque) {
+            Deque d = (Deque) c;
+            assertThrows(
+                NoSuchElementException.class,
+                () -> d.getFirst(),
+                () -> d.getLast(),
+                () -> d.removeFirst(),
+                () -> d.removeLast(),
+                () -> d.pop(),
+                () -> d.descendingIterator().next());
+        }
+    }
+
+    public void testRemoveIf() {
+        Collection c = impl.emptyCollection();
+        boolean ordered =
+            c.spliterator().hasCharacteristics(Spliterator.ORDERED);
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        int n = rnd.nextInt(6);
+        for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
+        AtomicReference threwAt = new AtomicReference(null);
+        List orig = rnd.nextBoolean()
+            ? new ArrayList(c)
+            : Arrays.asList(c.toArray());
+
+        // Merely creating an iterator can change ArrayBlockingQueue behavior
+        Iterator it = rnd.nextBoolean() ? c.iterator() : null;
+
+        ArrayList survivors = new ArrayList();
+        ArrayList accepts = new ArrayList();
+        ArrayList rejects = new ArrayList();
+
+        Predicate randomPredicate = e -> {
+            assertNull(threwAt.get());
+            switch (rnd.nextInt(3)) {
+            case 0: accepts.add(e); return true;
+            case 1: rejects.add(e); return false;
+            case 2: threwAt.set(e); throw new ArithmeticException();
+            default: throw new AssertionError();
+            }
+        };
+        try {
+            try {
+                boolean modified = c.removeIf(randomPredicate);
+                assertNull(threwAt.get());
+                assertEquals(modified, accepts.size() > 0);
+                assertEquals(modified, rejects.size() != n);
+                assertEquals(accepts.size() + rejects.size(), n);
+                if (ordered) {
+                    assertEquals(rejects,
+                                 Arrays.asList(c.toArray()));
+                } else {
+                    assertEquals(new HashSet(rejects),
+                                 new HashSet(Arrays.asList(c.toArray())));
+                }
+            } catch (ArithmeticException ok) {
+                assertNotNull(threwAt.get());
+                assertTrue(c.contains(threwAt.get()));
+            }
+            if (it != null && impl.isConcurrent())
+                // check for weakly consistent iterator
+                while (it.hasNext()) assertTrue(orig.contains(it.next()));
+            switch (rnd.nextInt(4)) {
+            case 0: survivors.addAll(c); break;
+            case 1: survivors.addAll(Arrays.asList(c.toArray())); break;
+            case 2: c.forEach(survivors::add); break;
+            case 3: for (Object e : c) survivors.add(e); break;
+            }
+            assertTrue(orig.containsAll(accepts));
+            assertTrue(orig.containsAll(rejects));
+            assertTrue(orig.containsAll(survivors));
+            assertTrue(orig.containsAll(c));
+            assertTrue(c.containsAll(rejects));
+            assertTrue(c.containsAll(survivors));
+            assertTrue(survivors.containsAll(rejects));
+            if (threwAt.get() == null) {
+                assertEquals(n - accepts.size(), c.size());
+                for (Object x : accepts) assertFalse(c.contains(x));
+            } else {
+                // Two acceptable behaviors: entire removeIf call is one
+                // transaction, or each element processed is one transaction.
+                assertTrue(n == c.size() || n == c.size() + accepts.size());
+                int k = 0;
+                for (Object x : accepts) if (c.contains(x)) k++;
+                assertTrue(k == accepts.size() || k == 0);
+            }
+        } catch (Throwable ex) {
+            System.err.println(impl.klazz());
+            // c is at risk of corruption if we got here, so be lenient
+            try { System.err.printf("c=%s%n", c); }
+            catch (Throwable t) { t.printStackTrace(); }
+            System.err.printf("n=%d%n", n);
+            System.err.printf("orig=%s%n", orig);
+            System.err.printf("accepts=%s%n", accepts);
+            System.err.printf("rejects=%s%n", rejects);
+            System.err.printf("survivors=%s%n", survivors);
+            System.err.printf("threwAt=%s%n", threwAt.get());
+            throw ex;
+        }
+    }
+
+    /**
+     * Various ways of traversing a collection yield same elements
+     */
+    public void testIteratorEquivalence() {
+        Collection c = impl.emptyCollection();
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        int n = rnd.nextInt(6);
+        for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
+        ArrayList iterated = new ArrayList();
+        ArrayList iteratedForEachRemaining = new ArrayList();
+        ArrayList tryAdvanced = new ArrayList();
+        ArrayList spliterated = new ArrayList();
+        ArrayList splitonced = new ArrayList();
+        ArrayList forEached = new ArrayList();
+        ArrayList streamForEached = new ArrayList();
+        ConcurrentLinkedQueue parallelStreamForEached = new ConcurrentLinkedQueue();
+        ArrayList removeIfed = new ArrayList();
+        for (Object x : c) iterated.add(x);
+        c.iterator().forEachRemaining(iteratedForEachRemaining::add);
+        for (Spliterator s = c.spliterator();
+             s.tryAdvance(tryAdvanced::add); ) {}
+        c.spliterator().forEachRemaining(spliterated::add);
+        {                       // trySplit returns "strict prefix"
+            Spliterator s1 = c.spliterator(), s2 = s1.trySplit();
+            if (s2 != null) s2.forEachRemaining(splitonced::add);
+            s1.forEachRemaining(splitonced::add);
+        }
+        c.forEach(forEached::add);
+        c.stream().forEach(streamForEached::add);
+        c.parallelStream().forEach(parallelStreamForEached::add);
+        c.removeIf(e -> { removeIfed.add(e); return false; });
+        boolean ordered =
+            c.spliterator().hasCharacteristics(Spliterator.ORDERED);
+        if (c instanceof List || c instanceof Deque)
+            assertTrue(ordered);
+        HashSet cset = new HashSet(c);
+        assertEquals(cset, new HashSet(parallelStreamForEached));
+        if (ordered) {
+            assertEquals(iterated, iteratedForEachRemaining);
+            assertEquals(iterated, tryAdvanced);
+            assertEquals(iterated, spliterated);
+            assertEquals(iterated, splitonced);
+            assertEquals(iterated, forEached);
+            assertEquals(iterated, streamForEached);
+            assertEquals(iterated, removeIfed);
+        } else {
+            assertEquals(cset, new HashSet(iterated));
+            assertEquals(cset, new HashSet(iteratedForEachRemaining));
+            assertEquals(cset, new HashSet(tryAdvanced));
+            assertEquals(cset, new HashSet(spliterated));
+            assertEquals(cset, new HashSet(splitonced));
+            assertEquals(cset, new HashSet(forEached));
+            assertEquals(cset, new HashSet(streamForEached));
+            assertEquals(cset, new HashSet(removeIfed));
+        }
+        if (c instanceof Deque) {
+            Deque d = (Deque) c;
+            ArrayList descending = new ArrayList();
+            ArrayList descendingForEachRemaining = new ArrayList();
+            for (Iterator it = d.descendingIterator(); it.hasNext(); )
+                descending.add(it.next());
+            d.descendingIterator().forEachRemaining(
+                e -> descendingForEachRemaining.add(e));
+            Collections.reverse(descending);
+            Collections.reverse(descendingForEachRemaining);
+            assertEquals(iterated, descending);
+            assertEquals(iterated, descendingForEachRemaining);
+        }
+    }
+
+    /**
+     * Calling Iterator#remove() after Iterator#forEachRemaining
+     * should (maybe) remove last element
+     */
+    public void testRemoveAfterForEachRemaining() {
+        Collection c = impl.emptyCollection();
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        testCollection: {
+            int n = 3 + rnd.nextInt(2);
+            for (int i = 0; i < n; i++) c.add(impl.makeElement(i));
+            Iterator it = c.iterator();
+            assertTrue(it.hasNext());
+            assertEquals(impl.makeElement(0), it.next());
+            assertTrue(it.hasNext());
+            assertEquals(impl.makeElement(1), it.next());
+            it.forEachRemaining(e -> assertTrue(c.contains(e)));
+            if (testImplementationDetails) {
+                if (c instanceof java.util.concurrent.ArrayBlockingQueue) {
+                    assertIteratorExhausted(it);
+                } else {
+                    try { it.remove(); }
+                    catch (UnsupportedOperationException ok) {
+                        break testCollection;
+                    }
+                    assertEquals(n - 1, c.size());
+                    for (int i = 0; i < n - 1; i++)
+                        assertTrue(c.contains(impl.makeElement(i)));
+                    assertFalse(c.contains(impl.makeElement(n - 1)));
+                }
+            }
+        }
+        if (c instanceof Deque) {
+            Deque d = (Deque) impl.emptyCollection();
+            int n = 3 + rnd.nextInt(2);
+            for (int i = 0; i < n; i++) d.add(impl.makeElement(i));
+            Iterator it = d.descendingIterator();
+            assertTrue(it.hasNext());
+            assertEquals(impl.makeElement(n - 1), it.next());
+            assertTrue(it.hasNext());
+            assertEquals(impl.makeElement(n - 2), it.next());
+            it.forEachRemaining(e -> assertTrue(c.contains(e)));
+            if (testImplementationDetails) {
+                it.remove();
+                assertEquals(n - 1, d.size());
+                for (int i = 1; i < n; i++)
+                    assertTrue(d.contains(impl.makeElement(i)));
+                assertFalse(d.contains(impl.makeElement(0)));
+            }
+        }
+    }
+
     /**
      * stream().forEach returns elements in the collection
      */
-    public void testForEach() throws Throwable {
+    public void testStreamForEach() throws Throwable {
         final Collection c = impl.emptyCollection();
         final AtomicLong count = new AtomicLong(0L);
         final Object x = impl.makeElement(1);
         final Object y = impl.makeElement(2);
         final ArrayList found = new ArrayList();
-        Consumer<Object> spy = (o) -> { found.add(o); };
+        Consumer<Object> spy = o -> found.add(o);
         c.stream().forEach(spy);
         assertTrue(found.isEmpty());
 
@@ -96,7 +519,7 @@
         assertTrue(found.isEmpty());
     }
 
-    public void testForEachConcurrentStressTest() throws Throwable {
+    public void testStreamForEachConcurrentStressTest() throws Throwable {
         if (!impl.isConcurrent()) return;
         final Collection c = impl.emptyCollection();
         final long testDurationMillis = timeoutMillis();
@@ -109,7 +532,7 @@
             Runnable checkElt = () -> {
                 threadsStarted.countDown();
                 while (!done.get())
-                    c.stream().forEach((x) -> { assertSame(x, elt); }); };
+                    c.stream().forEach(x -> assertSame(x, elt)); };
             Runnable addRemove = () -> {
                 threadsStarted.countDown();
                 while (!done.get()) {
@@ -124,5 +547,144 @@
         assertNull(f2.get(0L, MILLISECONDS));
     }
 
-    // public void testCollection8DebugFail() { fail(); }
+    /**
+     * collection.forEach returns elements in the collection
+     */
+    public void testForEach() throws Throwable {
+        final Collection c = impl.emptyCollection();
+        final AtomicLong count = new AtomicLong(0L);
+        final Object x = impl.makeElement(1);
+        final Object y = impl.makeElement(2);
+        final ArrayList found = new ArrayList();
+        Consumer<Object> spy = o -> found.add(o);
+        c.forEach(spy);
+        assertTrue(found.isEmpty());
+
+        assertTrue(c.add(x));
+        c.forEach(spy);
+        assertEquals(Collections.singletonList(x), found);
+        found.clear();
+
+        assertTrue(c.add(y));
+        c.forEach(spy);
+        assertEquals(2, found.size());
+        assertTrue(found.contains(x));
+        assertTrue(found.contains(y));
+        found.clear();
+
+        c.clear();
+        c.forEach(spy);
+        assertTrue(found.isEmpty());
+    }
+
+    /**
+     * Motley crew of threads concurrently randomly hammer the collection.
+     */
+    public void testDetectRaces() throws Throwable {
+        if (!impl.isConcurrent()) return;
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        final Collection c = impl.emptyCollection();
+        final long testDurationMillis
+            = expensiveTests ? LONG_DELAY_MS : timeoutMillis();
+        final AtomicBoolean done = new AtomicBoolean(false);
+        final Object one = impl.makeElement(1);
+        final Object two = impl.makeElement(2);
+        final Consumer checkSanity = x -> assertTrue(x == one || x == two);
+        final Consumer<Object[]> checkArraySanity = array -> {
+            // assertTrue(array.length <= 2); // duplicates are permitted
+            for (Object x : array) assertTrue(x == one || x == two);
+        };
+        final Object[] emptyArray =
+            (Object[]) java.lang.reflect.Array.newInstance(one.getClass(), 0);
+        final List<Future<?>> futures;
+        final Phaser threadsStarted = new Phaser(1); // register this thread
+        final Runnable[] frobbers = {
+            () -> c.forEach(checkSanity),
+            () -> c.stream().forEach(checkSanity),
+            () -> c.parallelStream().forEach(checkSanity),
+            () -> c.spliterator().trySplit(),
+            () -> {
+                Spliterator s = c.spliterator();
+                s.tryAdvance(checkSanity);
+                s.trySplit();
+            },
+            () -> {
+                Spliterator s = c.spliterator();
+                do {} while (s.tryAdvance(checkSanity));
+            },
+            () -> { for (Object x : c) checkSanity.accept(x); },
+            () -> checkArraySanity.accept(c.toArray()),
+            () -> checkArraySanity.accept(c.toArray(emptyArray)),
+            () -> {
+                assertTrue(c.add(one));
+                assertTrue(c.contains(one));
+                assertTrue(c.remove(one));
+                assertFalse(c.contains(one));
+            },
+            () -> {
+                assertTrue(c.add(two));
+                assertTrue(c.contains(two));
+                assertTrue(c.remove(two));
+                assertFalse(c.contains(two));
+            },
+        };
+        final List<Runnable> tasks =
+            Arrays.stream(frobbers)
+            .filter(task -> rnd.nextBoolean()) // random subset
+            .map(task -> (Runnable) () -> {
+                     threadsStarted.arriveAndAwaitAdvance();
+                     while (!done.get())
+                         task.run();
+                 })
+            .collect(Collectors.toList());
+        final ExecutorService pool = Executors.newCachedThreadPool();
+        try (PoolCleaner cleaner = cleaner(pool, done)) {
+            threadsStarted.bulkRegister(tasks.size());
+            futures = tasks.stream()
+                .map(pool::submit)
+                .collect(Collectors.toList());
+            threadsStarted.arriveAndDeregister();
+            Thread.sleep(testDurationMillis);
+        }
+        for (Future future : futures)
+            assertNull(future.get(0L, MILLISECONDS));
+    }
+
+    /**
+     * Spliterators are either IMMUTABLE or truly late-binding or, if
+     * concurrent, use the same "late-binding style" of returning
+     * elements added between creation and first use.
+     */
+    public void testLateBindingStyle() {
+        if (!testImplementationDetails) return;
+        if (impl.klazz() == ArrayList.class) return; // for jdk8
+        // Immutable (snapshot) spliterators are exempt
+        if (impl.emptyCollection().spliterator()
+            .hasCharacteristics(Spliterator.IMMUTABLE))
+            return;
+        final Object one = impl.makeElement(1);
+        {
+            final Collection c = impl.emptyCollection();
+            final Spliterator split = c.spliterator();
+            c.add(one);
+            assertTrue(split.tryAdvance(e -> { assertSame(e, one); }));
+            assertFalse(split.tryAdvance(e -> { throw new AssertionError(); }));
+            assertTrue(c.contains(one));
+        }
+        {
+            final AtomicLong count = new AtomicLong(0);
+            final Collection c = impl.emptyCollection();
+            final Spliterator split = c.spliterator();
+            c.add(one);
+            split.forEachRemaining(
+                e -> { assertSame(e, one); count.getAndIncrement(); });
+            assertEquals(1L, count.get());
+            assertFalse(split.tryAdvance(e -> { throw new AssertionError(); }));
+            assertTrue(c.contains(one));
+        }
+    }
+
+//     public void testCollection8DebugFail() {
+//         fail(impl.klazz().getSimpleName());
+//     }
 }
diff --git a/jdk/test/java/util/concurrent/tck/CollectionTest.java b/jdk/test/java/util/concurrent/tck/CollectionTest.java
index 7b532af..8ec2014 100644
--- a/jdk/test/java/util/concurrent/tck/CollectionTest.java
+++ b/jdk/test/java/util/concurrent/tck/CollectionTest.java
@@ -32,8 +32,6 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
-import java.util.Collection;
-
 import junit.framework.Test;
 
 /**
@@ -58,11 +56,7 @@
                                         impl));
     }
 
-    /** A test of the CollectionImplementation implementation ! */
-    public void testEmptyMeansEmpty() {
-        assertTrue(impl.emptyCollection().isEmpty());
-        assertEquals(0, impl.emptyCollection().size());
-    }
-
-    // public void testCollectionDebugFail() { fail(); }
+//     public void testCollectionDebugFail() {
+//         fail(impl.klazz().getSimpleName());
+//     }
 }
diff --git a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
index 12f7ee9..bc81edf 100644
--- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
+++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java
@@ -174,26 +174,26 @@
 
     void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
         checkCompletedExceptionally(f, true,
-            (t) -> assertTrue(t instanceof CFException));
+            t -> assertTrue(t instanceof CFException));
     }
 
     void checkCompletedWithWrappedCancellationException(CompletableFuture<?> f) {
         checkCompletedExceptionally(f, true,
-            (t) -> assertTrue(t instanceof CancellationException));
+            t -> assertTrue(t instanceof CancellationException));
     }
 
     void checkCompletedWithTimeoutException(CompletableFuture<?> f) {
         checkCompletedExceptionally(f, false,
-            (t) -> assertTrue(t instanceof TimeoutException));
+            t -> assertTrue(t instanceof TimeoutException));
     }
 
     void checkCompletedWithWrappedException(CompletableFuture<?> f,
                                             Throwable ex) {
-        checkCompletedExceptionally(f, true, (t) -> assertSame(t, ex));
+        checkCompletedExceptionally(f, true, t -> assertSame(t, ex));
     }
 
     void checkCompletedExceptionally(CompletableFuture<?> f, Throwable ex) {
-        checkCompletedExceptionally(f, false, (t) -> assertSame(t, ex));
+        checkCompletedExceptionally(f, false, t -> assertSame(t, ex));
     }
 
     void checkCancelled(CompletableFuture<?> f) {
@@ -3284,12 +3284,12 @@
 
             () -> f.thenApply(null),
             () -> f.thenApplyAsync(null),
-            () -> f.thenApplyAsync((x) -> x, null),
+            () -> f.thenApplyAsync(x -> x, null),
             () -> f.thenApplyAsync(null, exec),
 
             () -> f.thenAccept(null),
             () -> f.thenAcceptAsync(null),
-            () -> f.thenAcceptAsync((x) -> {} , null),
+            () -> f.thenAcceptAsync(x -> {} , null),
             () -> f.thenAcceptAsync(null, exec),
 
             () -> f.thenRun(null),
@@ -3324,18 +3324,18 @@
             () -> f.applyToEither(g, null),
             () -> f.applyToEitherAsync(g, null),
             () -> f.applyToEitherAsync(g, null, exec),
-            () -> f.applyToEither(nullFuture, (x) -> x),
-            () -> f.applyToEitherAsync(nullFuture, (x) -> x),
-            () -> f.applyToEitherAsync(nullFuture, (x) -> x, exec),
-            () -> f.applyToEitherAsync(g, (x) -> x, null),
+            () -> f.applyToEither(nullFuture, x -> x),
+            () -> f.applyToEitherAsync(nullFuture, x -> x),
+            () -> f.applyToEitherAsync(nullFuture, x -> x, exec),
+            () -> f.applyToEitherAsync(g, x -> x, null),
 
             () -> f.acceptEither(g, null),
             () -> f.acceptEitherAsync(g, null),
             () -> f.acceptEitherAsync(g, null, exec),
-            () -> f.acceptEither(nullFuture, (x) -> {}),
-            () -> f.acceptEitherAsync(nullFuture, (x) -> {}),
-            () -> f.acceptEitherAsync(nullFuture, (x) -> {}, exec),
-            () -> f.acceptEitherAsync(g, (x) -> {}, null),
+            () -> f.acceptEither(nullFuture, x -> {}),
+            () -> f.acceptEitherAsync(nullFuture, x -> {}),
+            () -> f.acceptEitherAsync(nullFuture, x -> {}, exec),
+            () -> f.acceptEitherAsync(g, x -> {}, null),
 
             () -> f.runAfterEither(g, null),
             () -> f.runAfterEitherAsync(g, null),
@@ -3401,18 +3401,18 @@
         for (CompletableFuture<Integer> src : srcs) {
             List<CompletableFuture<?>> fs = new ArrayList<>();
             fs.add(src.thenRunAsync(() -> {}, e));
-            fs.add(src.thenAcceptAsync((z) -> {}, e));
-            fs.add(src.thenApplyAsync((z) -> z, e));
+            fs.add(src.thenAcceptAsync(z -> {}, e));
+            fs.add(src.thenApplyAsync(z -> z, e));
 
             fs.add(src.thenCombineAsync(src, (x, y) -> x, e));
             fs.add(src.thenAcceptBothAsync(src, (x, y) -> {}, e));
             fs.add(src.runAfterBothAsync(src, () -> {}, e));
 
-            fs.add(src.applyToEitherAsync(src, (z) -> z, e));
-            fs.add(src.acceptEitherAsync(src, (z) -> {}, e));
+            fs.add(src.applyToEitherAsync(src, z -> z, e));
+            fs.add(src.acceptEitherAsync(src, z -> {}, e));
             fs.add(src.runAfterEitherAsync(src, () -> {}, e));
 
-            fs.add(src.thenComposeAsync((z) -> null, e));
+            fs.add(src.thenComposeAsync(z -> null, e));
             fs.add(src.whenCompleteAsync((z, t) -> {}, e));
             fs.add(src.handleAsync((z, t) -> null, e));
 
@@ -3445,11 +3445,11 @@
         {
             List<CompletableFuture<?>> fs = new ArrayList<>();
 
-            fs.add(complete.applyToEitherAsync(incomplete, (z) -> z, e));
-            fs.add(incomplete.applyToEitherAsync(complete, (z) -> z, e));
+            fs.add(complete.applyToEitherAsync(incomplete, z -> z, e));
+            fs.add(incomplete.applyToEitherAsync(complete, z -> z, e));
 
-            fs.add(complete.acceptEitherAsync(incomplete, (z) -> {}, e));
-            fs.add(incomplete.acceptEitherAsync(complete, (z) -> {}, e));
+            fs.add(complete.acceptEitherAsync(incomplete, z -> {}, e));
+            fs.add(incomplete.acceptEitherAsync(complete, z -> {}, e));
 
             fs.add(complete.runAfterEitherAsync(incomplete, () -> {}, e));
             fs.add(incomplete.runAfterEitherAsync(complete, () -> {}, e));
@@ -3488,18 +3488,18 @@
 
         List<CompletableFuture<?>> fs = new ArrayList<>();
         fs.add(incomplete.thenRunAsync(() -> {}, e));
-        fs.add(incomplete.thenAcceptAsync((z) -> {}, e));
-        fs.add(incomplete.thenApplyAsync((z) -> z, e));
+        fs.add(incomplete.thenAcceptAsync(z -> {}, e));
+        fs.add(incomplete.thenApplyAsync(z -> z, e));
 
         fs.add(incomplete.thenCombineAsync(incomplete, (x, y) -> x, e));
         fs.add(incomplete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
         fs.add(incomplete.runAfterBothAsync(incomplete, () -> {}, e));
 
-        fs.add(incomplete.applyToEitherAsync(incomplete, (z) -> z, e));
-        fs.add(incomplete.acceptEitherAsync(incomplete, (z) -> {}, e));
+        fs.add(incomplete.applyToEitherAsync(incomplete, z -> z, e));
+        fs.add(incomplete.acceptEitherAsync(incomplete, z -> {}, e));
         fs.add(incomplete.runAfterEitherAsync(incomplete, () -> {}, e));
 
-        fs.add(incomplete.thenComposeAsync((z) -> null, e));
+        fs.add(incomplete.thenComposeAsync(z -> null, e));
         fs.add(incomplete.whenCompleteAsync((z, t) -> {}, e));
         fs.add(incomplete.handleAsync((z, t) -> null, e));
 
@@ -3720,7 +3720,7 @@
     public void testCompleteAsync2() {
         CompletableFuture<Integer> f = new CompletableFuture<>();
         CFException ex = new CFException();
-        f.completeAsync(() -> {if (true) throw ex; return 1;});
+        f.completeAsync(() -> { throw ex; });
         try {
             f.join();
             shouldThrow();
@@ -3750,7 +3750,7 @@
         CompletableFuture<Integer> f = new CompletableFuture<>();
         CFException ex = new CFException();
         ThreadExecutor executor = new ThreadExecutor();
-        f.completeAsync(() -> {if (true) throw ex; return 1;}, executor);
+        f.completeAsync(() -> { throw ex; }, executor);
         try {
             f.join();
             shouldThrow();
@@ -3909,31 +3909,31 @@
         List<Function<CompletableFuture<Integer>, CompletableFuture<?>>> funs
             = new ArrayList<>();
 
-        funs.add((y) -> m.thenRun(y, noopRunnable));
-        funs.add((y) -> m.thenAccept(y, noopConsumer));
-        funs.add((y) -> m.thenApply(y, incFunction));
+        funs.add(y -> m.thenRun(y, noopRunnable));
+        funs.add(y -> m.thenAccept(y, noopConsumer));
+        funs.add(y -> m.thenApply(y, incFunction));
 
-        funs.add((y) -> m.runAfterEither(y, incomplete, noopRunnable));
-        funs.add((y) -> m.acceptEither(y, incomplete, noopConsumer));
-        funs.add((y) -> m.applyToEither(y, incomplete, incFunction));
+        funs.add(y -> m.runAfterEither(y, incomplete, noopRunnable));
+        funs.add(y -> m.acceptEither(y, incomplete, noopConsumer));
+        funs.add(y -> m.applyToEither(y, incomplete, incFunction));
 
-        funs.add((y) -> m.runAfterBoth(y, v42, noopRunnable));
-        funs.add((y) -> m.runAfterBoth(v42, y, noopRunnable));
-        funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
-        funs.add((y) -> m.thenAcceptBoth(v42, y, new SubtractAction(m)));
-        funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m)));
-        funs.add((y) -> m.thenCombine(v42, y, new SubtractFunction(m)));
+        funs.add(y -> m.runAfterBoth(y, v42, noopRunnable));
+        funs.add(y -> m.runAfterBoth(v42, y, noopRunnable));
+        funs.add(y -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
+        funs.add(y -> m.thenAcceptBoth(v42, y, new SubtractAction(m)));
+        funs.add(y -> m.thenCombine(y, v42, new SubtractFunction(m)));
+        funs.add(y -> m.thenCombine(v42, y, new SubtractFunction(m)));
 
-        funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
+        funs.add(y -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
 
-        funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m)));
+        funs.add(y -> m.thenCompose(y, new CompletableFutureInc(m)));
 
-        funs.add((y) -> CompletableFuture.allOf(y));
-        funs.add((y) -> CompletableFuture.allOf(y, v42));
-        funs.add((y) -> CompletableFuture.allOf(v42, y));
-        funs.add((y) -> CompletableFuture.anyOf(y));
-        funs.add((y) -> CompletableFuture.anyOf(y, incomplete));
-        funs.add((y) -> CompletableFuture.anyOf(incomplete, y));
+        funs.add(y -> CompletableFuture.allOf(y));
+        funs.add(y -> CompletableFuture.allOf(y, v42));
+        funs.add(y -> CompletableFuture.allOf(v42, y));
+        funs.add(y -> CompletableFuture.anyOf(y));
+        funs.add(y -> CompletableFuture.anyOf(y, incomplete));
+        funs.add(y -> CompletableFuture.anyOf(incomplete, y));
 
         for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                  fun : funs) {
@@ -3990,12 +3990,12 @@
     public void testMinimalCompletionStage_minimality() {
         if (!testImplementationDetails) return;
         Function<Method, String> toSignature =
-            (method) -> method.getName() + Arrays.toString(method.getParameterTypes());
+            method -> method.getName() + Arrays.toString(method.getParameterTypes());
         Predicate<Method> isNotStatic =
-            (method) -> (method.getModifiers() & Modifier.STATIC) == 0;
+            method -> (method.getModifiers() & Modifier.STATIC) == 0;
         List<Method> minimalMethods =
             Stream.of(Object.class, CompletionStage.class)
-            .flatMap((klazz) -> Stream.of(klazz.getMethods()))
+            .flatMap(klazz -> Stream.of(klazz.getMethods()))
             .filter(isNotStatic)
             .collect(Collectors.toList());
         // Methods from CompletableFuture permitted NOT to throw UOE
@@ -4011,7 +4011,7 @@
             .collect(Collectors.toSet());
         List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods())
             .filter(isNotStatic)
-            .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
+            .filter(method -> !permittedMethodSignatures.contains(toSignature.apply(method)))
             .collect(Collectors.toList());
 
         List<CompletionStage<Integer>> stages = new ArrayList<>();
@@ -4171,7 +4171,7 @@
         CompletionStage<Integer> minimal = f.minimalCompletionStage();
         CompletableFuture<Integer> g = new CompletableFuture<>();
         if (!createIncomplete) assertTrue(f.complete(v1));
-        minimal.thenAccept((x) -> g.complete(x));
+        minimal.thenAccept(x -> g.complete(x));
         if (createIncomplete) assertTrue(f.complete(v1));
         g.join();
         checkCompletedNormally(g, v1);
@@ -4195,7 +4195,7 @@
         static <T,U,V> Function<T, CompletableFuture<V>> compose
             (Function<T, CompletableFuture<U>> f,
              Function<U, CompletableFuture<V>> g) {
-            return (x) -> f.apply(x).thenCompose(g);
+            return x -> f.apply(x).thenCompose(g);
         }
 
         static void assertZero(CompletableFuture<?> f) {
@@ -4275,9 +4275,9 @@
 
         // Some mutually non-commutative functions
         Function<Long, CompletableFuture<Long>> triple
-            = (x) -> Monad.unit(3 * x);
+            = x -> Monad.unit(3 * x);
         Function<Long, CompletableFuture<Long>> inc
-            = (x) -> Monad.unit(x + 1);
+            = x -> Monad.unit(x + 1);
 
         // unit is a right identity: m >>= unit === m
         Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit),
@@ -4289,7 +4289,7 @@
         // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) )
         Monad.assertFutureEquals(
             unit.apply(5L).thenCompose(inc).thenCompose(triple),
-            unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple)));
+            unit.apply(5L).thenCompose(x -> inc.apply(x).thenCompose(triple)));
 
         // The case for CompletableFuture as an additive monad is weaker...
 
@@ -4299,7 +4299,7 @@
         // left zero: zero >>= f === zero
         Monad.assertZero(zero.thenCompose(inc));
         // right zero: f >>= (\x -> zero) === zero
-        Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero));
+        Monad.assertZero(inc.apply(5L).thenCompose(x -> zero));
 
         // f plus zero === f
         Monad.assertFutureEquals(Monad.unit(5L),
@@ -4357,8 +4357,8 @@
         final AtomicInteger count = new AtomicInteger(0);
         for (int i = 0; i < n; i++) {
             head.thenRun(() -> count.getAndIncrement());
-            head.thenAccept((x) -> count.getAndIncrement());
-            head.thenApply((x) -> count.getAndIncrement());
+            head.thenAccept(x -> count.getAndIncrement());
+            head.thenApply(x -> count.getAndIncrement());
 
             head.runAfterBoth(complete, () -> count.getAndIncrement());
             head.thenAcceptBoth(complete, (x, y) -> count.getAndIncrement());
@@ -4368,11 +4368,11 @@
             complete.thenCombine(head, (x, y) -> count.getAndIncrement());
 
             head.runAfterEither(new CompletableFuture<Void>(), () -> count.getAndIncrement());
-            head.acceptEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
-            head.applyToEither(new CompletableFuture<Void>(), (x) -> count.getAndIncrement());
+            head.acceptEither(new CompletableFuture<Void>(), x -> count.getAndIncrement());
+            head.applyToEither(new CompletableFuture<Void>(), x -> count.getAndIncrement());
             new CompletableFuture<Void>().runAfterEither(head, () -> count.getAndIncrement());
-            new CompletableFuture<Void>().acceptEither(head, (x) -> count.getAndIncrement());
-            new CompletableFuture<Void>().applyToEither(head, (x) -> count.getAndIncrement());
+            new CompletableFuture<Void>().acceptEither(head, x -> count.getAndIncrement());
+            new CompletableFuture<Void>().applyToEither(head, x -> count.getAndIncrement());
         }
         head.complete(null);
         assertEquals(5 * 3 * n, count.get());
@@ -4389,11 +4389,11 @@
             f.complete(null);
 
             f = new CompletableFuture<>();
-            f.acceptEither(incomplete, (x) -> {});
+            f.acceptEither(incomplete, x -> {});
             f.complete(null);
 
             f = new CompletableFuture<>();
-            f.applyToEither(incomplete, (x) -> x);
+            f.applyToEither(incomplete, x -> x);
             f.complete(null);
 
             f = new CompletableFuture<>();
@@ -4407,11 +4407,11 @@
             f.complete(null);
 
             f = new CompletableFuture<>();
-            incomplete.acceptEither(f, (x) -> {});
+            incomplete.acceptEither(f, x -> {});
             f.complete(null);
 
             f = new CompletableFuture<>();
-            incomplete.applyToEither(f, (x) -> x);
+            incomplete.applyToEither(f, x -> x);
             f.complete(null);
 
             f = new CompletableFuture<>();
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
index fd62ada..00f8dc6 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMap8Test.java
@@ -43,6 +43,8 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.Spliterator;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.LongAdder;
 import java.util.function.BiFunction;
@@ -88,7 +90,7 @@
      */
     public void testComputeIfAbsent() {
         ConcurrentHashMap map = map5();
-        map.computeIfAbsent(six, (x) -> "Z");
+        map.computeIfAbsent(six, x -> "Z");
         assertTrue(map.containsKey(six));
     }
 
@@ -97,7 +99,7 @@
      */
     public void testComputeIfAbsent2() {
         ConcurrentHashMap map = map5();
-        assertEquals("A", map.computeIfAbsent(one, (x) -> "Z"));
+        assertEquals("A", map.computeIfAbsent(one, x -> "Z"));
     }
 
     /**
@@ -105,7 +107,7 @@
      */
     public void testComputeIfAbsent3() {
         ConcurrentHashMap map = map5();
-        map.computeIfAbsent(six, (x) -> null);
+        map.computeIfAbsent(six, x -> null);
         assertFalse(map.containsKey(six));
     }
 
@@ -1114,4 +1116,30 @@
         assertNull(r);
     }
 
+    /**
+     * Tests performance of computeIfAbsent when the element is present.
+     * See JDK-8161372
+     * ant -Djsr166.tckTestClass=ConcurrentHashMapTest -Djsr166.methodFilter=testcomputeIfAbsent_performance -Djsr166.expensiveTests=true tck
+     */
+    public void testcomputeIfAbsent_performance() {
+        final int mapSize = 20;
+        final int iterations = expensiveTests ? (1 << 23) : mapSize * 2;
+        final int threads = expensiveTests ? 10 : 2;
+        final ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
+        for (int i = 0; i < mapSize; i++)
+            map.put(i, i);
+        final ExecutorService pool = Executors.newFixedThreadPool(2);
+        try (PoolCleaner cleaner = cleaner(pool)) {
+            Runnable r = new CheckedRunnable() {
+                public void realRun() {
+                    int result = 0;
+                    for (int i = 0; i < iterations; i++)
+                        result += map.computeIfAbsent(i % mapSize, k -> k + k);
+                    if (result == -42) throw new Error();
+                }};
+            for (int i = 0; i < threads; i++)
+                pool.execute(r);
+        }
+    }
+
 }
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java
index 26095ad..b6e6f72 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java
@@ -864,30 +864,4 @@
         assertEquals(mapSize, map.size());
     }
 
-    /**
-     * Tests performance of computeIfAbsent when the element is present.
-     * See JDK-8161372
-     * ant -Djsr166.tckTestClass=ConcurrentHashMapTest -Djsr166.methodFilter=testcomputeIfAbsent_performance -Djsr166.expensiveTests=true tck
-     */
-    public void testcomputeIfAbsent_performance() {
-        final int mapSize = 20;
-        final int iterations = expensiveTests ? (1 << 23) : mapSize * 2;
-        final int threads = expensiveTests ? 10 : 2;
-        final ConcurrentHashMap<Integer, Integer> map = new ConcurrentHashMap<>();
-        for (int i = 0; i < mapSize; i++)
-            map.put(i, i);
-        final ExecutorService pool = Executors.newFixedThreadPool(2);
-        try (PoolCleaner cleaner = cleaner(pool)) {
-            Runnable r = new CheckedRunnable() {
-                public void realRun() {
-                    int result = 0;
-                    for (int i = 0; i < iterations; i++)
-                        result += map.computeIfAbsent(i % mapSize, (k) -> k + k);
-                    if (result == -42) throw new Error();
-                }};
-            for (int i = 0; i < threads; i++)
-                pool.execute(r);
-        }
-    }
-
 }
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
index daab538..bf1c055 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
@@ -52,12 +52,20 @@
     }
 
     public static Test suite() {
-        return new TestSuite(ConcurrentLinkedDequeTest.class);
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return ConcurrentLinkedDeque.class; }
+            public Collection emptyCollection() { return new ConcurrentLinkedDeque(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
+        return newTestSuite(ConcurrentLinkedDequeTest.class,
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /**
      * Returns a new deque of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private ConcurrentLinkedDeque<Integer> populatedDeque(int n) {
         ConcurrentLinkedDeque<Integer> q = new ConcurrentLinkedDeque<Integer>();
@@ -66,6 +74,8 @@
             assertTrue(q.offer(new Integer(i)));
         assertFalse(q.isEmpty());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peekFirst());
+        assertEquals((Integer) (n - 1), q.peekLast());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
index bafaa65..1c3a65b 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
@@ -50,12 +50,20 @@
     }
 
     public static Test suite() {
-        return new TestSuite(ConcurrentLinkedQueueTest.class);
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return ConcurrentLinkedQueue.class; }
+            public Collection emptyCollection() { return new ConcurrentLinkedQueue(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
+        return newTestSuite(ConcurrentLinkedQueueTest.class,
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /**
      * Returns a new queue of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private ConcurrentLinkedQueue<Integer> populatedQueue(int n) {
         ConcurrentLinkedQueue<Integer> q = new ConcurrentLinkedQueue<Integer>();
@@ -64,6 +72,7 @@
             assertTrue(q.offer(new Integer(i)));
         assertFalse(q.isEmpty());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peek());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
index 28c9f6b..ae91219 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSetTest.java
@@ -62,7 +62,7 @@
 
     /**
      * Returns a new set of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private ConcurrentSkipListSet<Integer> populatedSet(int n) {
         ConcurrentSkipListSet<Integer> q =
diff --git a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java
index bad618f..4b299e7 100644
--- a/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentSkipListSubSetTest.java
@@ -57,7 +57,7 @@
 
     /**
      * Returns a new set of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private NavigableSet<Integer> populatedSet(int n) {
         ConcurrentSkipListSet<Integer> q =
diff --git a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java
index c457f6b..5863cd2 100644
--- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java
+++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java
@@ -53,7 +53,22 @@
     }
 
     public static Test suite() {
-        return new TestSuite(CopyOnWriteArrayListTest.class);
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return ArrayList.class; }
+            public List emptyCollection() { return new CopyOnWriteArrayList(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return true; }
+        }
+        class SubListImplementation extends Implementation {
+            public List emptyCollection() {
+                return super.emptyCollection().subList(0, 0);
+            }
+        }
+        return newTestSuite(
+                CopyOnWriteArrayListTest.class,
+                CollectionTest.testSuite(new Implementation()),
+                CollectionTest.testSuite(new SubListImplementation()));
     }
 
     static CopyOnWriteArrayList<Integer> populatedArray(int n) {
diff --git a/jdk/test/java/util/concurrent/tck/CountedCompleter8Test.java b/jdk/test/java/util/concurrent/tck/CountedCompleter8Test.java
new file mode 100644
index 0000000..eb23564
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/CountedCompleter8Test.java
@@ -0,0 +1,168 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.util.concurrent.CountedCompleter;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class CountedCompleter8Test extends JSR166TestCase {
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        return new TestSuite(CountedCompleter8Test.class);
+    }
+
+    /** CountedCompleter class javadoc code sample, version 1. */
+    public static <E> void forEach1(E[] array, Consumer<E> action) {
+        class Task extends CountedCompleter<Void> {
+            final int lo, hi;
+            Task(Task parent, int lo, int hi) {
+                super(parent); this.lo = lo; this.hi = hi;
+            }
+
+            public void compute() {
+                if (hi - lo >= 2) {
+                    int mid = (lo + hi) >>> 1;
+                    // must set pending count before fork
+                    setPendingCount(2);
+                    new Task(this, mid, hi).fork(); // right child
+                    new Task(this, lo, mid).fork(); // left child
+                }
+                else if (hi > lo)
+                    action.accept(array[lo]);
+                tryComplete();
+            }
+        }
+        new Task(null, 0, array.length).invoke();
+    }
+
+    /** CountedCompleter class javadoc code sample, version 2. */
+    public static <E> void forEach2(E[] array, Consumer<E> action) {
+        class Task extends CountedCompleter<Void> {
+            final int lo, hi;
+            Task(Task parent, int lo, int hi) {
+                super(parent); this.lo = lo; this.hi = hi;
+            }
+
+            public void compute() {
+                if (hi - lo >= 2) {
+                    int mid = (lo + hi) >>> 1;
+                    setPendingCount(1); // looks off by one, but correct!
+                    new Task(this, mid, hi).fork(); // right child
+                    new Task(this, lo, mid).compute(); // direct invoke
+                } else {
+                    if (hi > lo)
+                        action.accept(array[lo]);
+                    tryComplete();
+                }
+            }
+        }
+        new Task(null, 0, array.length).invoke();
+    }
+
+    /** CountedCompleter class javadoc code sample, version 3. */
+    public static <E> void forEach3(E[] array, Consumer<E> action) {
+        class Task extends CountedCompleter<Void> {
+            final int lo, hi;
+            Task(Task parent, int lo, int hi) {
+                super(parent); this.lo = lo; this.hi = hi;
+            }
+
+            public void compute() {
+                int n = hi - lo;
+                for (; n >= 2; n /= 2) {
+                    addToPendingCount(1);
+                    new Task(this, lo + n/2, lo + n).fork();
+                }
+                if (n > 0)
+                    action.accept(array[lo]);
+                propagateCompletion();
+            }
+        }
+        new Task(null, 0, array.length).invoke();
+    }
+
+    /** CountedCompleter class javadoc code sample, version 4. */
+    public static <E> void forEach4(E[] array, Consumer<E> action) {
+        class Task extends CountedCompleter<Void> {
+            final int lo, hi;
+            Task(Task parent, int lo, int hi) {
+                super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
+                this.lo = lo; this.hi = hi;
+            }
+
+            public void compute() {
+                for (int n = hi - lo; n >= 2; n /= 2)
+                    new Task(this, lo + n/2, lo + n).fork();
+                action.accept(array[lo]);
+                propagateCompletion();
+            }
+        }
+        if (array.length > 0)
+            new Task(null, 0, array.length).invoke();
+    }
+
+    void testRecursiveDecomposition(
+        BiConsumer<Integer[], Consumer<Integer>> action) {
+        int n = ThreadLocalRandom.current().nextInt(8);
+        Integer[] a = new Integer[n];
+        for (int i = 0; i < n; i++) a[i] = i + 1;
+        AtomicInteger ai = new AtomicInteger(0);
+        action.accept(a, ai::addAndGet);
+        assertEquals(n * (n + 1) / 2, ai.get());
+    }
+
+    /**
+     * Variants of divide-by-two recursive decomposition into leaf tasks,
+     * as described in the CountedCompleter class javadoc code samples
+     */
+    public void testRecursiveDecomposition() {
+        testRecursiveDecomposition(CountedCompleter8Test::forEach1);
+        testRecursiveDecomposition(CountedCompleter8Test::forEach2);
+        testRecursiveDecomposition(CountedCompleter8Test::forEach3);
+        testRecursiveDecomposition(CountedCompleter8Test::forEach4);
+    }
+
+}
diff --git a/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java
index 88ff1f3..afd4ccf 100644
--- a/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java
+++ b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java
@@ -44,8 +44,6 @@
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -1872,115 +1870,4 @@
         testInvokeOnPool(singletonPool(), a);
     }
 
-    /** CountedCompleter class javadoc code sample, version 1. */
-    public static <E> void forEach1(E[] array, Consumer<E> action) {
-        class Task extends CountedCompleter<Void> {
-            final int lo, hi;
-            Task(Task parent, int lo, int hi) {
-                super(parent); this.lo = lo; this.hi = hi;
-            }
-
-            public void compute() {
-                if (hi - lo >= 2) {
-                    int mid = (lo + hi) >>> 1;
-                    // must set pending count before fork
-                    setPendingCount(2);
-                    new Task(this, mid, hi).fork(); // right child
-                    new Task(this, lo, mid).fork(); // left child
-                }
-                else if (hi > lo)
-                    action.accept(array[lo]);
-                tryComplete();
-            }
-        }
-        new Task(null, 0, array.length).invoke();
-    }
-
-    /** CountedCompleter class javadoc code sample, version 2. */
-    public static <E> void forEach2(E[] array, Consumer<E> action) {
-        class Task extends CountedCompleter<Void> {
-            final int lo, hi;
-            Task(Task parent, int lo, int hi) {
-                super(parent); this.lo = lo; this.hi = hi;
-            }
-
-            public void compute() {
-                if (hi - lo >= 2) {
-                    int mid = (lo + hi) >>> 1;
-                    setPendingCount(1); // looks off by one, but correct!
-                    new Task(this, mid, hi).fork(); // right child
-                    new Task(this, lo, mid).compute(); // direct invoke
-                } else {
-                    if (hi > lo)
-                        action.accept(array[lo]);
-                    tryComplete();
-                }
-            }
-        }
-        new Task(null, 0, array.length).invoke();
-    }
-
-    /** CountedCompleter class javadoc code sample, version 3. */
-    public static <E> void forEach3(E[] array, Consumer<E> action) {
-        class Task extends CountedCompleter<Void> {
-            final int lo, hi;
-            Task(Task parent, int lo, int hi) {
-                super(parent); this.lo = lo; this.hi = hi;
-            }
-
-            public void compute() {
-                int n = hi - lo;
-                for (; n >= 2; n /= 2) {
-                    addToPendingCount(1);
-                    new Task(this, lo + n/2, lo + n).fork();
-                }
-                if (n > 0)
-                    action.accept(array[lo]);
-                propagateCompletion();
-            }
-        }
-        new Task(null, 0, array.length).invoke();
-    }
-
-    /** CountedCompleter class javadoc code sample, version 4. */
-    public static <E> void forEach4(E[] array, Consumer<E> action) {
-        class Task extends CountedCompleter<Void> {
-            final int lo, hi;
-            Task(Task parent, int lo, int hi) {
-                super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
-                this.lo = lo; this.hi = hi;
-            }
-
-            public void compute() {
-                for (int n = hi - lo; n >= 2; n /= 2)
-                    new Task(this, lo + n/2, lo + n).fork();
-                action.accept(array[lo]);
-                propagateCompletion();
-            }
-        }
-        if (array.length > 0)
-            new Task(null, 0, array.length).invoke();
-    }
-
-    void testRecursiveDecomposition(
-        BiConsumer<Integer[], Consumer<Integer>> action) {
-        int n = ThreadLocalRandom.current().nextInt(8);
-        Integer[] a = new Integer[n];
-        for (int i = 0; i < n; i++) a[i] = i + 1;
-        AtomicInteger ai = new AtomicInteger(0);
-        action.accept(a, (x) -> ai.addAndGet(x));
-        assertEquals(n * (n + 1) / 2, ai.get());
-    }
-
-    /**
-     * Variants of divide-by-two recursive decomposition into leaf tasks,
-     * as described in the CountedCompleter class javadoc code samples
-     */
-    public void testRecursiveDecomposition() {
-        testRecursiveDecomposition(CountedCompleterTest::forEach1);
-        testRecursiveDecomposition(CountedCompleterTest::forEach2);
-        testRecursiveDecomposition(CountedCompleterTest::forEach3);
-        testRecursiveDecomposition(CountedCompleterTest::forEach4);
-    }
-
 }
diff --git a/jdk/test/java/util/concurrent/tck/DelayQueueTest.java b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java
index d4a6bdc..41fd569 100644
--- a/jdk/test/java/util/concurrent/tck/DelayQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java
@@ -66,8 +66,16 @@
     }
 
     public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return DelayQueue.class; }
+            public Collection emptyCollection() { return new DelayQueue(); }
+            public Object makeElement(int i) { return new PDelay(i); }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
         return newTestSuite(DelayQueueTest.class,
-                            new Generic().testSuite());
+                            new Generic().testSuite(),
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /**
@@ -144,7 +152,7 @@
 
     /**
      * Returns a new queue of given size containing consecutive
-     * PDelays 0 ... n.
+     * PDelays 0 ... n - 1.
      */
     private DelayQueue<PDelay> populatedQueue(int n) {
         DelayQueue<PDelay> q = new DelayQueue<PDelay>();
@@ -156,6 +164,7 @@
         assertFalse(q.isEmpty());
         assertEquals(Integer.MAX_VALUE, q.remainingCapacity());
         assertEquals(n, q.size());
+        assertEquals(new PDelay(0), q.peek());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java
index d72d7dc..4ca78a0 100644
--- a/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java
+++ b/jdk/test/java/util/concurrent/tck/ExecutorCompletionService9Test.java
@@ -34,6 +34,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 import java.util.HashSet;
@@ -77,7 +78,7 @@
         List<Future<Integer>> futures = new ArrayList<>(n);
         Integer result = null;
         try {
-            solvers.forEach((solver) -> futures.add(cs.submit(solver)));
+            solvers.forEach(solver -> futures.add(cs.submit(solver)));
             for (int i = n; i > 0; i--) {
                 try {
                     Integer r = cs.take().get();
@@ -88,17 +89,17 @@
                 } catch (ExecutionException ignore) {}
             }
         } finally {
-            futures.forEach((future) -> future.cancel(true));
+            futures.forEach(future -> future.cancel(true));
         }
 
         if (result != null)
             use(result);
     }
 
-    HashSet<Integer> results;
+    ArrayList<Integer> results;
 
     void use(Integer x) {
-        if (results == null) results = new HashSet<Integer>();
+        if (results == null) results = new ArrayList<Integer>();
         results.add(x);
     }
 
@@ -107,6 +108,7 @@
      */
     public void testSolveAll()
         throws InterruptedException, ExecutionException {
+        results = null;
         Set<Callable<Integer>> solvers = Set.of(
             () -> null,
             () -> 1,
@@ -114,7 +116,8 @@
             () -> 3,
             () -> null);
         solveAll(cachedThreadPool, solvers);
-        assertEquals(Set.of(1, 2, 3), results);
+        results.sort(Comparator.naturalOrder());
+        assertEquals(List.of(1, 2, 3), results);
     }
 
     /**
@@ -122,6 +125,7 @@
      */
     public void testSolveAny()
         throws InterruptedException {
+        results = null;
         Set<Callable<Integer>> solvers = Set.of(
             () -> { throw new ArithmeticException(); },
             () -> null,
@@ -129,7 +133,7 @@
             () -> 2);
         solveAny(cachedThreadPool, solvers);
         assertEquals(1, results.size());
-        Integer elt = results.iterator().next();
+        Integer elt = results.get(0);
         assertTrue(elt.equals(1) || elt.equals(2));
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java
index 8a0360f..390639b 100644
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java
@@ -36,7 +36,8 @@
 /*
  * @test
  * @summary JSR-166 tck tests
- * @modules java.management
+ * @modules java.base/java.util.concurrent:open
+ *          java.management
  * @build *
  * @run junit/othervm/timeout=1000 -Djsr166.testImplementationDetails=true JSR166TestCase
  * @run junit/othervm/timeout=1000 -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 -Djsr166.testImplementationDetails=true JSR166TestCase
@@ -68,6 +69,7 @@
 import java.security.SecurityPermission;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.Enumeration;
@@ -474,6 +476,7 @@
             AbstractQueuedLongSynchronizerTest.suite(),
             ArrayBlockingQueueTest.suite(),
             ArrayDequeTest.suite(),
+            ArrayListTest.suite(),
             AtomicBooleanTest.suite(),
             AtomicIntegerArrayTest.suite(),
             AtomicIntegerFieldUpdaterTest.suite(),
@@ -496,6 +499,7 @@
             CopyOnWriteArrayListTest.suite(),
             CopyOnWriteArraySetTest.suite(),
             CountDownLatchTest.suite(),
+            CountedCompleterTest.suite(),
             CyclicBarrierTest.suite(),
             DelayQueueTest.suite(),
             EntryTest.suite(),
@@ -524,15 +528,17 @@
             TreeMapTest.suite(),
             TreeSetTest.suite(),
             TreeSubMapTest.suite(),
-            TreeSubSetTest.suite());
+            TreeSubSetTest.suite(),
+            VectorTest.suite());
 
         // Java8+ test classes
         if (atLeastJava8()) {
             String[] java8TestClassNames = {
+                "ArrayDeque8Test",
                 "Atomic8Test",
                 "CompletableFutureTest",
                 "ConcurrentHashMap8Test",
-                "CountedCompleterTest",
+                "CountedCompleter8Test",
                 "DoubleAccumulatorTest",
                 "DoubleAdderTest",
                 "ForkJoinPool8Test",
@@ -1850,12 +1856,22 @@
         }
     }
 
+    void assertImmutable(final Object o) {
+        if (o instanceof Collection) {
+            assertThrows(
+                UnsupportedOperationException.class,
+                new Runnable() { public void run() {
+                        ((Collection) o).add(null);}});
+        }
+    }
+
     @SuppressWarnings("unchecked")
     <T> T serialClone(T o) {
         try {
             ObjectInputStream ois = new ObjectInputStream
                 (new ByteArrayInputStream(serialBytes(o)));
             T clone = (T) ois.readObject();
+            if (o == clone) assertImmutable(o);
             assertSame(o.getClass(), clone.getClass());
             return clone;
         } catch (Throwable fail) {
@@ -1864,6 +1880,46 @@
         }
     }
 
+    /**
+     * A version of serialClone that leaves error handling (for
+     * e.g. NotSerializableException) up to the caller.
+     */
+    @SuppressWarnings("unchecked")
+    <T> T serialClonePossiblyFailing(T o)
+        throws ReflectiveOperationException, java.io.IOException {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        oos.writeObject(o);
+        oos.flush();
+        oos.close();
+        ObjectInputStream ois = new ObjectInputStream
+            (new ByteArrayInputStream(bos.toByteArray()));
+        T clone = (T) ois.readObject();
+        if (o == clone) assertImmutable(o);
+        assertSame(o.getClass(), clone.getClass());
+        return clone;
+    }
+
+    /**
+     * If o implements Cloneable and has a public clone method,
+     * returns a clone of o, else null.
+     */
+    @SuppressWarnings("unchecked")
+    <T> T cloneableClone(T o) {
+        if (!(o instanceof Cloneable)) return null;
+        final T clone;
+        try {
+            clone = (T) o.getClass().getMethod("clone").invoke(o);
+        } catch (NoSuchMethodException ok) {
+            return null;
+        } catch (ReflectiveOperationException unexpected) {
+            throw new Error(unexpected);
+        }
+        assertNotSame(o, clone); // not 100% guaranteed by spec
+        assertSame(o.getClass(), clone.getClass());
+        return clone;
+    }
+
     public void assertThrows(Class<? extends Throwable> expectedExceptionClass,
                              Runnable... throwingActions) {
         for (Runnable throwingAction : throwingActions) {
diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java
index 4950584..2559fdf 100644
--- a/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java
+++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingDequeTest.java
@@ -68,14 +68,22 @@
     }
 
     public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return LinkedBlockingDeque.class; }
+            public Collection emptyCollection() { return new LinkedBlockingDeque(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
         return newTestSuite(LinkedBlockingDequeTest.class,
                             new Unbounded().testSuite(),
-                            new Bounded().testSuite());
+                            new Bounded().testSuite(),
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /**
      * Returns a new deque of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private LinkedBlockingDeque<Integer> populatedDeque(int n) {
         LinkedBlockingDeque<Integer> q =
@@ -86,6 +94,8 @@
         assertFalse(q.isEmpty());
         assertEquals(0, q.remainingCapacity());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peekFirst());
+        assertEquals((Integer) (n - 1), q.peekLast());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java
index 125e6a5..153cbce 100644
--- a/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/LinkedBlockingQueueTest.java
@@ -68,14 +68,22 @@
     }
 
     public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return LinkedBlockingQueue.class; }
+            public Collection emptyCollection() { return new LinkedBlockingQueue(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
         return newTestSuite(LinkedBlockingQueueTest.class,
                             new Unbounded().testSuite(),
-                            new Bounded().testSuite());
+                            new Bounded().testSuite(),
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /**
      * Returns a new queue of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private LinkedBlockingQueue<Integer> populatedQueue(int n) {
         LinkedBlockingQueue<Integer> q =
@@ -86,6 +94,7 @@
         assertFalse(q.isEmpty());
         assertEquals(0, q.remainingCapacity());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peek());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/LinkedListTest.java b/jdk/test/java/util/concurrent/tck/LinkedListTest.java
index ea0f689..471d52d 100644
--- a/jdk/test/java/util/concurrent/tck/LinkedListTest.java
+++ b/jdk/test/java/util/concurrent/tck/LinkedListTest.java
@@ -48,12 +48,27 @@
     }
 
     public static Test suite() {
-        return new TestSuite(LinkedListTest.class);
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return LinkedList.class; }
+            public Collection emptyCollection() { return new LinkedList(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return false; }
+            public boolean permitsNulls() { return true; }
+        }
+        class SubListImplementation extends Implementation {
+            public Collection emptyCollection() {
+                return new LinkedList().subList(0, 0);
+            }
+        }
+        return newTestSuite(
+                LinkedListTest.class,
+                CollectionTest.testSuite(new Implementation()),
+                CollectionTest.testSuite(new SubListImplementation()));
     }
 
     /**
      * Returns a new queue of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private LinkedList<Integer> populatedQueue(int n) {
         LinkedList<Integer> q = new LinkedList<Integer>();
@@ -62,6 +77,8 @@
             assertTrue(q.offer(new Integer(i)));
         assertFalse(q.isEmpty());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peekFirst());
+        assertEquals((Integer) (n - 1), q.peekLast());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java
index dd57870..6abec8a 100644
--- a/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java
@@ -51,14 +51,6 @@
 
 @SuppressWarnings({"unchecked", "rawtypes"})
 public class LinkedTransferQueueTest extends JSR166TestCase {
-    static class Implementation implements CollectionImplementation {
-        public Class<?> klazz() { return LinkedTransferQueue.class; }
-        public Collection emptyCollection() { return new LinkedTransferQueue(); }
-        public Object makeElement(int i) { return i; }
-        public boolean isConcurrent() { return true; }
-        public boolean permitsNulls() { return false; }
-    }
-
     public static class Generic extends BlockingQueueTest {
         protected BlockingQueue emptyCollection() {
             return new LinkedTransferQueue();
@@ -70,6 +62,13 @@
     }
 
     public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return LinkedTransferQueue.class; }
+            public Collection emptyCollection() { return new LinkedTransferQueue(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
         return newTestSuite(LinkedTransferQueueTest.class,
                             new Generic().testSuite(),
                             CollectionTest.testSuite(new Implementation()));
diff --git a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java
index 7b22c6e..088c389 100644
--- a/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/PriorityBlockingQueueTest.java
@@ -69,9 +69,17 @@
     }
 
     public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return PriorityBlockingQueue.class; }
+            public Collection emptyCollection() { return new PriorityBlockingQueue(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return true; }
+            public boolean permitsNulls() { return false; }
+        }
         return newTestSuite(PriorityBlockingQueueTest.class,
                             new Generic().testSuite(),
-                            new InitialCapacity().testSuite());
+                            new InitialCapacity().testSuite(),
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     /** Sample Comparator */
@@ -83,7 +91,7 @@
 
     /**
      * Returns a new queue of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private PriorityBlockingQueue<Integer> populatedQueue(int n) {
         PriorityBlockingQueue<Integer> q =
@@ -96,6 +104,7 @@
         assertFalse(q.isEmpty());
         assertEquals(Integer.MAX_VALUE, q.remainingCapacity());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peek());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java
index e16497e..91e155d 100644
--- a/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java
+++ b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java
@@ -49,7 +49,15 @@
         main(suite(), args);
     }
     public static Test suite() {
-        return new TestSuite(PriorityQueueTest.class);
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return PriorityQueue.class; }
+            public Collection emptyCollection() { return new PriorityQueue(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return false; }
+            public boolean permitsNulls() { return false; }
+        }
+        return newTestSuite(PriorityQueueTest.class,
+                            CollectionTest.testSuite(new Implementation()));
     }
 
     static class MyReverseComparator implements Comparator {
@@ -60,7 +68,7 @@
 
     /**
      * Returns a new queue of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private PriorityQueue<Integer> populatedQueue(int n) {
         PriorityQueue<Integer> q = new PriorityQueue<Integer>(n);
@@ -71,6 +79,7 @@
             assertTrue(q.offer(new Integer(i)));
         assertFalse(q.isEmpty());
         assertEquals(n, q.size());
+        assertEquals((Integer) 0, q.peek());
         return q;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/StampedLockTest.java b/jdk/test/java/util/concurrent/tck/StampedLockTest.java
index a03be99..ea0b8f9 100644
--- a/jdk/test/java/util/concurrent/tck/StampedLockTest.java
+++ b/jdk/test/java/util/concurrent/tck/StampedLockTest.java
@@ -110,12 +110,12 @@
 
     List<Function<StampedLock, Long>> readLockers() {
         List<Function<StampedLock, Long>> readLockers = new ArrayList<>();
-        readLockers.add((sl) -> sl.readLock());
-        readLockers.add((sl) -> sl.tryReadLock());
-        readLockers.add((sl) -> readLockInterruptiblyUninterrupted(sl));
-        readLockers.add((sl) -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
-        readLockers.add((sl) -> tryReadLockUninterrupted(sl, 0L, DAYS));
-        readLockers.add((sl) -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
+        readLockers.add(sl -> sl.readLock());
+        readLockers.add(sl -> sl.tryReadLock());
+        readLockers.add(sl -> readLockInterruptiblyUninterrupted(sl));
+        readLockers.add(sl -> tryReadLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        readLockers.add(sl -> tryReadLockUninterrupted(sl, 0L, DAYS));
+        readLockers.add(sl -> sl.tryConvertToReadLock(sl.tryOptimisticRead()));
         return readLockers;
     }
 
@@ -131,12 +131,12 @@
 
     List<Function<StampedLock, Long>> writeLockers() {
         List<Function<StampedLock, Long>> writeLockers = new ArrayList<>();
-        writeLockers.add((sl) -> sl.writeLock());
-        writeLockers.add((sl) -> sl.tryWriteLock());
-        writeLockers.add((sl) -> writeLockInterruptiblyUninterrupted(sl));
-        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
-        writeLockers.add((sl) -> tryWriteLockUninterrupted(sl, 0L, DAYS));
-        writeLockers.add((sl) -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
+        writeLockers.add(sl -> sl.writeLock());
+        writeLockers.add(sl -> sl.tryWriteLock());
+        writeLockers.add(sl -> writeLockInterruptiblyUninterrupted(sl));
+        writeLockers.add(sl -> tryWriteLockUninterrupted(sl, Long.MIN_VALUE, DAYS));
+        writeLockers.add(sl -> tryWriteLockUninterrupted(sl, 0L, DAYS));
+        writeLockers.add(sl -> sl.tryConvertToWriteLock(sl.tryOptimisticRead()));
         return writeLockers;
     }
 
diff --git a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java
index d72f1af..9478cf3 100644
--- a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java
+++ b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java
@@ -963,7 +963,7 @@
         AtomicInteger sum = new AtomicInteger();
         SubmissionPublisher<Integer> p = basicPublisher();
         CompletableFuture<Void> f =
-            p.consume((Integer x) -> { sum.getAndAdd(x.intValue()); });
+            p.consume((Integer x) -> sum.getAndAdd(x.intValue()));
         int n = 20;
         for (int i = 1; i <= n; ++i)
             p.submit(i);
diff --git a/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java b/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java
index c80af62..eef34d3 100644
--- a/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java
+++ b/jdk/test/java/util/concurrent/tck/ThreadLocalRandom8Test.java
@@ -259,4 +259,20 @@
         assertEquals(size, counter.sum());
     }
 
+    /**
+     * A deserialized ThreadLocalRandom is always identical to
+     * ThreadLocalRandom.current()
+     */
+    public void testSerialization() {
+        assertSame(
+            ThreadLocalRandom.current(),
+            serialClone(ThreadLocalRandom.current()));
+        // In the current implementation, there is exactly one shared instance
+        if (testImplementationDetails)
+            assertSame(
+                ThreadLocalRandom.current(),
+                java.util.concurrent.CompletableFuture.supplyAsync(
+                    () -> serialClone(ThreadLocalRandom.current())).join());
+    }
+
 }
diff --git a/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java b/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java
index da50bbe..394bc46 100644
--- a/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java
+++ b/jdk/test/java/util/concurrent/tck/ThreadLocalRandomTest.java
@@ -79,6 +79,41 @@
     }
 
     /**
+     * Repeated calls to next (only accessible via reflection) produce
+     * at least two distinct results, and repeated calls produce all
+     * possible values.
+     */
+    public void testNext() throws ReflectiveOperationException {
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+        try {
+            java.lang.reflect.Method m
+                = ThreadLocalRandom.class.getDeclaredMethod(
+                    "next", new Class[] { int.class });
+            m.setAccessible(true);
+
+            int i;
+            {
+                int val = new java.util.Random().nextInt(4);
+                for (i = 0; i < NCALLS; i++) {
+                    int q = (int) m.invoke(rnd, new Object[] { 2 });
+                    if (val == q) break;
+                }
+                assertTrue(i < NCALLS);
+            }
+
+            {
+                int r = (int) m.invoke(rnd, new Object[] { 3 });
+                for (i = 0; i < NCALLS; i++) {
+                    int q = (int) m.invoke(rnd, new Object[] { 3 });
+                    assertTrue(q < (1<<3));
+                    if (r != q) break;
+                }
+                assertTrue(i < NCALLS);
+            }
+        } catch (SecurityException acceptable) {}
+    }
+
+    /**
      * Repeated calls to nextInt produce at least two distinct results
      */
     public void testNextInt() {
diff --git a/jdk/test/java/util/concurrent/tck/TreeSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSetTest.java
index dc5b007..af37e4c 100644
--- a/jdk/test/java/util/concurrent/tck/TreeSetTest.java
+++ b/jdk/test/java/util/concurrent/tck/TreeSetTest.java
@@ -67,7 +67,7 @@
 
     /**
      * Returns a new set of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private TreeSet<Integer> populatedSet(int n) {
         TreeSet<Integer> q = new TreeSet<Integer>();
diff --git a/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java
index afc0604..b8cc70a 100644
--- a/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java
+++ b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java
@@ -58,7 +58,7 @@
 
     /**
      * Returns a new set of given size containing consecutive
-     * Integers 0 ... n.
+     * Integers 0 ... n - 1.
      */
     private NavigableSet<Integer> populatedSet(int n) {
         TreeSet<Integer> q = new TreeSet<Integer>();
diff --git a/jdk/test/java/util/concurrent/tck/VectorTest.java b/jdk/test/java/util/concurrent/tck/VectorTest.java
new file mode 100644
index 0000000..087b0ed
--- /dev/null
+++ b/jdk/test/java/util/concurrent/tck/VectorTest.java
@@ -0,0 +1,66 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Vector;
+import java.util.Collection;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class VectorTest extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        class Implementation implements CollectionImplementation {
+            public Class<?> klazz() { return Vector.class; }
+            public List emptyCollection() { return new Vector(); }
+            public Object makeElement(int i) { return i; }
+            public boolean isConcurrent() { return false; }
+            public boolean permitsNulls() { return true; }
+        }
+        class SubListImplementation extends Implementation {
+            public List emptyCollection() {
+                return super.emptyCollection().subList(0, 0);
+            }
+        }
+        return newTestSuite(
+                // VectorTest.class,
+                CollectionTest.testSuite(new Implementation()),
+                CollectionTest.testSuite(new SubListImplementation()));
+    }
+
+}
diff --git a/jdk/test/java/util/logging/FileHandlerLongLimit.java b/jdk/test/java/util/logging/FileHandlerLongLimit.java
index d081af5..028e14e 100644
--- a/jdk/test/java/util/logging/FileHandlerLongLimit.java
+++ b/jdk/test/java/util/logging/FileHandlerLongLimit.java
@@ -52,6 +52,7 @@
  * @test
  * @bug 8059767
  * @summary tests that FileHandler can accept a long limit.
+ * @modules java.logging/java.util.logging:open
  * @run main/othervm FileHandlerLongLimit UNSECURE
  * @run main/othervm FileHandlerLongLimit SECURE
  * @author danielfuchs
diff --git a/jdk/test/java/util/logging/HandlersConfigTest.java b/jdk/test/java/util/logging/HandlersConfigTest.java
index 7d122cd..705c451 100644
--- a/jdk/test/java/util/logging/HandlersConfigTest.java
+++ b/jdk/test/java/util/logging/HandlersConfigTest.java
@@ -28,6 +28,7 @@
  *          configured correctly from defaults and/or LogManager properties
  *          as specified in javadoc and that no special
  *          logging permission is required for instantiating them.
+ * @modules java.logging/java.util.logging:open
  * @run main/othervm HandlersConfigTest default
  * @run main/othervm HandlersConfigTest configured
  */
diff --git a/jdk/test/java/util/logging/LocalizedLevelName.java b/jdk/test/java/util/logging/LocalizedLevelName.java
index 561e2d1..627789f 100644
--- a/jdk/test/java/util/logging/LocalizedLevelName.java
+++ b/jdk/test/java/util/logging/LocalizedLevelName.java
@@ -29,6 +29,7 @@
  * @test
  * @bug 8016127 8024131
  * @summary test logging.properties localized
+ * @modules java.logging/sun.util.logging.resources:open
  * @run main/othervm LocalizedLevelName
  */
 
diff --git a/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/UpdateConfigurationTest.java b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/UpdateConfigurationTest.java
index 7022593..b456518 100644
--- a/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/UpdateConfigurationTest.java
+++ b/jdk/test/java/util/logging/LogManager/Configuration/updateConfiguration/UpdateConfigurationTest.java
@@ -61,6 +61,7 @@
  * @test
  * @bug 8033661
  * @summary tests LogManager.updateConfiguration(bin)
+ * @modules java.logging/java.util.logging:open
  * @run main/othervm UpdateConfigurationTest UNSECURE
  * @run main/othervm UpdateConfigurationTest SECURE
  * @author danielfuchs
diff --git a/jdk/test/java/util/logging/modules/pkgs/p3/test/ResourceBundleTest.java b/jdk/test/java/util/logging/modules/pkgs/p3/test/ResourceBundleTest.java
index 2989a78..03d2614 100644
--- a/jdk/test/java/util/logging/modules/pkgs/p3/test/ResourceBundleTest.java
+++ b/jdk/test/java/util/logging/modules/pkgs/p3/test/ResourceBundleTest.java
@@ -136,10 +136,6 @@
         // class resource bundle in another named module m1.
         failToLoadResourceBundle("mylogger.g", "p1.resource.ClassResource",
                 true, NAMED_NEGATIVE_CLASSBUNDLE_MSG);
-        // in named module m2, try to create a logger with
-        // class resource bundle in an unnamed module.
-        failToLoadResourceBundle("mylogger.h", "p3.resource.ClassResource",
-                true, NAMED_NEGATIVE_CLASSBUNDLE_MSG);
     }
 
     static void failToLoadPropertyRBs() {
@@ -153,10 +149,6 @@
         // property resource bundle in another named module m1.
         failToLoadResourceBundle("mylogger.k", "p1.resource.p",
                 true, NAMED_NEGATIVE_PROPERTYBUNDLE_MSG);
-        // in named module m2, try to create a logger with
-        // property resource bundle in an unnamed module.
-        failToLoadResourceBundle("mylogger.l", "p3.resource.p",
-                true, NAMED_NEGATIVE_PROPERTYBUNDLE_MSG);
     }
 
     static void failToLoadResourceBundle(String loggerName, String rbName,
diff --git a/jdk/test/javax/crypto/CryptoPermissions/CryptoPolicyFallback.java b/jdk/test/javax/crypto/CryptoPermissions/CryptoPolicyFallback.java
new file mode 100644
index 0000000..8ccdd0c
--- /dev/null
+++ b/jdk/test/javax/crypto/CryptoPermissions/CryptoPolicyFallback.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8169335
+ * @summary Add a crypto policy fallback in case Security Property
+ * 'crypto.policy' does not exist.
+ * @run main/othervm CryptoPolicyFallback
+ */
+import java.io.*;
+import java.nio.file.*;
+import java.util.stream.*;
+import javax.crypto.*;
+
+/*
+ * Take the current java.security file, strip out the 'crypto.policy' entry,
+ * write to a new file in the current directory, then use that file as the
+ * replacement java.security file.  This test will fail if the crypto.policy
+ * entry doesn't match the compiled in value.
+ */
+public class CryptoPolicyFallback {
+
+    private static final String FILENAME = "java.security";
+
+    public static void main(String[] args) throws Exception {
+
+        String javaHome = System.getProperty("java.home");
+
+        Path path = Paths.get(javaHome, "conf", "security", FILENAME);
+
+        /*
+         * Get the default value.
+         */
+        String defaultPolicy;
+        try (Stream<String> lines = Files.lines(path)) {
+            /*
+             * If the input java.security file is malformed
+             * (missing crypto.policy, attribute/no value, etc), throw
+             * exception.  split() might throw AIOOB which
+             * is ok behavior.
+             */
+            defaultPolicy = lines.filter(x -> x.startsWith("crypto.policy="))
+                    .findFirst().orElseThrow(
+                            () -> new Exception("Missing crypto.policy"))
+                    .split("=")[1].trim();
+        }
+
+        /*
+         * We know there is at least one crypto.policy entry, strip
+         * all of them out of the java.security file.
+         */
+        try (PrintWriter out = new PrintWriter(FILENAME);
+                Stream<String> lines = Files.lines(path)) {
+            lines.filter(x -> !x.trim().startsWith("crypto.policy="))
+                    .forEach(out::println);
+        }
+
+        /*
+         * "-Djava.security.properties==file" does a complete replacement
+         * of the system java.security file.  i.e. value must be "=file"
+         */
+        System.setProperty("java.security.properties", "=" + FILENAME);
+
+        /*
+         * Find out expected value.
+         */
+        int expected;
+        switch (defaultPolicy) {
+        case "limited":
+            expected = 128;
+            break;
+        case "unlimited":
+            expected = Integer.MAX_VALUE;
+            break;
+        default:
+            throw new Exception(
+                    "Unexpected Default Policy Value: " + defaultPolicy);
+        }
+
+        /*
+         * Do the actual check.  If the JCE Framework can't initialize
+         * an Exception is normally thrown here.
+         */
+        int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
+
+        System.out.println("Default Policy: " + defaultPolicy
+                + "\nExpected max AES key length: " + expected
+                + ", received : " + maxKeyLen);
+
+        if (expected != maxKeyLen) {
+            throw new Exception("Wrong Key Length size!");
+        }
+
+        System.out.println("PASSED!");
+    }
+}
diff --git a/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java b/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java
index e6a8f7f..a367021 100644
--- a/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java
+++ b/jdk/test/javax/crypto/CryptoPermissions/TestUnlimited.java
@@ -27,10 +27,11 @@
  * @test
  * @bug 8061842
  * @summary Package jurisdiction policy files as something other than JAR
+ * @run main/othervm TestUnlimited use_default default
  * @run main/othervm TestUnlimited "" exception
- * @run main/othervm TestUnlimited limited fail
- * @run main/othervm TestUnlimited unlimited pass
- * @run main/othervm TestUnlimited unlimited/ pass
+ * @run main/othervm TestUnlimited limited limited
+ * @run main/othervm TestUnlimited unlimited unlimited
+ * @run main/othervm TestUnlimited unlimited/ unlimited
  * @run main/othervm TestUnlimited NosuchDir exception
  * @run main/othervm TestUnlimited . exception
  * @run main/othervm TestUnlimited /tmp/unlimited exception
@@ -40,9 +41,38 @@
  */
 import javax.crypto.*;
 import java.security.Security;
+import java.nio.file.*;
+import java.util.stream.*;
 
 public class TestUnlimited {
 
+    private enum Result {
+        UNLIMITED,
+        LIMITED,
+        EXCEPTION,
+        UNKNOWN
+    };
+
+    /*
+     * Grab the default policy entry from java.security.
+     *
+     * If the input java.security file is malformed
+     * (missing crypto.policy, attribute/no value, etc), throw
+     * exception.  split() might throw AIOOB which
+     * is ok behavior.
+     */
+    private static String getDefaultPolicy() throws Exception {
+        String javaHome = System.getProperty("java.home");
+        Path path = Paths.get(javaHome, "conf", "security", "java.security");
+
+        try (Stream<String> lines = Files.lines(path)) {
+            return lines.filter(x -> x.startsWith("crypto.policy="))
+                    .findFirst().orElseThrow(
+                            () -> new Exception("Missing crypto.policy"))
+                    .split("=")[1].trim();
+        }
+    }
+
     public static void main(String[] args) throws Exception {
         /*
          * Override the Security property to allow for unlimited policy.
@@ -53,16 +83,37 @@
             throw new Exception("Two args required");
         }
 
-        boolean expected = args[1].equals("pass");
-        boolean exception = args[1].equals("exception");
-        boolean result = false;
+        String testStr = args[0];
+        String expectedStr = args[1];
+        if (testStr.equals("use_default")) {
+            expectedStr = getDefaultPolicy();
+        }
 
-        System.out.println("Testing: " + args[0]);
+        Result expected = Result.UNKNOWN;  // avoid NPE warnings
+        Result result;
 
-        if (args[0].equals("\"\"")) {
+        switch (expectedStr) {
+        case "unlimited":
+            expected = Result.UNLIMITED;
+            break;
+        case "limited":
+            expected = Result.LIMITED;
+            break;
+        case "exception":
+            expected = Result.EXCEPTION;
+            break;
+        default:
+            throw new Exception("Unexpected argument");
+        }
+
+        System.out.println("Testing: " + testStr);
+        if (testStr.equals("\"\"")) {
             Security.setProperty("crypto.policy", "");
         } else {
-            Security.setProperty("crypto.policy", args[0]);
+            // skip default case.
+            if (!testStr.equals("use_default")) {
+                Security.setProperty("crypto.policy", testStr);
+            }
         }
 
         /*
@@ -74,21 +125,20 @@
             System.out.println("max AES key len:" + maxKeyLen);
             if (maxKeyLen > 128) {
                 System.out.println("Unlimited policy is active");
-                result = true;
+                result = Result.UNLIMITED;
             } else {
                 System.out.println("Unlimited policy is NOT active");
-                result = false;
+                result = Result.LIMITED;
             }
         } catch (Throwable e) {
-            if (!exception) {
-                throw new Exception();
-            }
+            //ExceptionInInitializerError's
+            result = Result.EXCEPTION;
         }
 
         System.out.println(
                 "Expected:\t" + expected + "\nResult:\t\t" + result);
-        if (expected != result) {
-            throw new Exception();
+        if (!expected.equals(result)) {
+            throw new Exception("Didn't match");
         }
 
         System.out.println("DONE!");
diff --git a/jdk/test/javax/management/ObjectName/CompressedStorageTest.java b/jdk/test/javax/management/ObjectName/CompressedStorageTest.java
index eac3d35..a7f3d36 100644
--- a/jdk/test/javax/management/ObjectName/CompressedStorageTest.java
+++ b/jdk/test/javax/management/ObjectName/CompressedStorageTest.java
@@ -27,7 +27,7 @@
  * @summary Tests the limits imposed on the domain name part of an
  *          ObjectName instance
  * @author Jaroslav Bachorik
- * @modules java.management
+ * @modules java.management/javax.management:open
  * @run main CompressedStorageTest
  */
 
diff --git a/jdk/test/javax/management/loading/MLetInternalsTest.java b/jdk/test/javax/management/loading/MLetInternalsTest.java
index 48318ac..4d31272 100644
--- a/jdk/test/javax/management/loading/MLetInternalsTest.java
+++ b/jdk/test/javax/management/loading/MLetInternalsTest.java
@@ -36,7 +36,7 @@
  * @bug 8058089
  * @summary Tests various internal functions provided by MLet for correctness
  * @author Jaroslav Bachorik
- * @modules java.management
+ * @modules java.management/javax.management.loading:open
  * @run testng MLetInternalsTest
  */
 public class MLetInternalsTest {
diff --git a/jdk/test/javax/management/openmbean/TabularDataOrderTest.java b/jdk/test/javax/management/openmbean/TabularDataOrderTest.java
index 32ce7a3..68e9fef 100644
--- a/jdk/test/javax/management/openmbean/TabularDataOrderTest.java
+++ b/jdk/test/javax/management/openmbean/TabularDataOrderTest.java
@@ -26,7 +26,7 @@
  * @bug 6334663
  * @summary Test that TabularDataSupport preserves the order elements were added
  * @author Eamonn McManus
- * @modules java.management
+ * @modules java.management/javax.management.openmbean:open
  */
 
 import java.io.ByteArrayInputStream;
diff --git a/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java b/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java
index 44a5911..acf21cb 100644
--- a/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java
+++ b/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java
@@ -29,7 +29,7 @@
  *          thrown when constructor is invoked with null class loader as
  *          an argument.
  * @author Amit Sapre
- * @modules java.management
+ * @modules java.management/javax.management.remote.rmi:open
  * @run clean ObjectInputStreamWithLoaderNullCheckTest
  * @run build ObjectInputStreamWithLoaderNullCheckTest
  * @run main ObjectInputStreamWithLoaderNullCheckTest
diff --git a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java
index 9e24325..3b86bc8 100644
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectionIdTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 4901808 7183800
- * @summary Check that RMI connection ids include client host name
+ * @summary Check that RMI connection ids include IP address of a client network interface
  * @author Eamonn McManus
  * @modules java.management
  * @run clean RMIConnectionIdTest
@@ -39,7 +39,7 @@
 public class RMIConnectionIdTest {
     public static void main(String[] args) throws Exception {
         System.out.println("Testing that RMI connection id includes " +
-                           "client host name");
+                           "IP address of a client network interface");
         MBeanServer mbs = MBeanServerFactory.createMBeanServer();
         JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
         JMXConnectorServer cs =
@@ -61,11 +61,9 @@
         }
         String clientAddr = rest.substring(0, spaceIndex);
         InetAddress clientInetAddr = InetAddress.getByName(clientAddr);
-        InetAddress localAddr = clientInetAddr.isLoopbackAddress() ? InetAddress.getLoopbackAddress() : InetAddress.getLocalHost();
-        System.out.println("InetAddresses: local=" + localAddr + "; " +
-                           "connectionId=" + clientInetAddr);
-        if (!localAddr.equals(clientInetAddr)) {
-            System.out.println("TEST FAILS: addresses differ");
+        NetworkInterface ni = NetworkInterface.getByInetAddress(clientInetAddr);
+        if (ni == null) {
+            System.out.println("TEST FAILS: address not found");
             System.exit(1);
         }
         cc.close();
diff --git a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java
index 276e231..a6063f1 100644
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java
@@ -42,7 +42,7 @@
  * @bug 6566891
  * @summary Check no memory leak on RMIConnector's rmbscMap
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management/javax.management.remote.rmi:open
  * @run clean RMIConnectorInternalMapTest
  * @run build RMIConnectorInternalMapTest
  * @run main RMIConnectorInternalMapTest
diff --git a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java
index 1872a13..5b616a7 100644
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java
@@ -38,7 +38,7 @@
  * @bug 6566891
  * @summary Check no memory leak on RMIConnector's nullSubjectConn
  * @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management/javax.management.remote.rmi:open
  * @run clean RMIConnectorNullSubjectConnTest
  * @run build RMIConnectorNullSubjectConnTest
  * @run main RMIConnectorNullSubjectConnTest
diff --git a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java
index 50777b0..b202163 100644
--- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java
+++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java
@@ -25,7 +25,8 @@
  * @test
  * @bug 6957378
  * @summary Test that a listener can be removed remotely from an MBean that no longer exists.
- * @modules java.management/com.sun.jmx.remote.internal
+ * @modules java.management/javax.management.remote.rmi:open
+ *          java.management/com.sun.jmx.remote.internal:+open
  * @author Eamonn McManus
  * @run main/othervm -XX:+UsePerfData DeadListenerTest
  */
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSBufferOverflowUnderflowTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSBufferOverflowUnderflowTest.java
index 8ebbc44..ea34bf8 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSBufferOverflowUnderflowTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSBufferOverflowUnderflowTest.java
@@ -30,8 +30,8 @@
  * @modules java.security.jgss
  *          jdk.security.auth
  *          java.base/sun.security.util
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSDataExchangeTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSDataExchangeTest.java
index 94f3a1b..d712379 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSDataExchangeTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSDataExchangeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSEnginesClosureTest.java
index fc987a3..25a3a68 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSEnginesClosureTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSEnginesClosureTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeTest.java
index aaf155d5..5215d82 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeWithReplicatedPacketsTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeWithReplicatedPacketsTest.java
index b3b26bc..d3db82c 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeWithReplicatedPacketsTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSHandshakeWithReplicatedPacketsTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSIncorrectAppDataTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSIncorrectAppDataTest.java
index 9bc2b10..c19e58a 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSIncorrectAppDataTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSIncorrectAppDataTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSMFLNTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSMFLNTest.java
index e44246fc..bfeb6c9 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSMFLNTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSMFLNTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSNotEnabledRC4Test.java b/jdk/test/javax/net/ssl/DTLS/DTLSNotEnabledRC4Test.java
index 3b5bee3..a7614d2 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSNotEnabledRC4Test.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSNotEnabledRC4Test.java
@@ -27,10 +27,10 @@
  * @summary Testing DTLS engines do not enable RC4 ciphers by default.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS DTLSNotEnabledRC4Test
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeTest.java
index 2e1c9d5..a1ef8ce 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithCipherChangeTest.java
index ff7bac9..bfe5b7e 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithCipherChangeTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithCipherChangeTest.java
@@ -29,10 +29,10 @@
  * @key randomness
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithDataExTest.java
index dff5a8a..5a76104 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithDataExTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSRehandshakeWithDataExTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSSequenceNumberTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSSequenceNumberTest.java
index 7eb019d..1475f8b 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSSequenceNumberTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSSequenceNumberTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS
diff --git a/jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java
index e7c5174..3eef84e 100644
--- a/jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSUnsupportedCiphersTest.java
@@ -28,10 +28,10 @@
  *          causes IllegalArgumentException.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLS DTLSUnsupportedCiphersTest
diff --git a/jdk/test/javax/net/ssl/DTLS/TEST.properties b/jdk/test/javax/net/ssl/DTLS/TEST.properties
index 080af05..7f6fae9 100644
--- a/jdk/test/javax/net/ssl/DTLS/TEST.properties
+++ b/jdk/test/javax/net/ssl/DTLS/TEST.properties
@@ -1,7 +1,7 @@
 modules = \
-    java.security.jgss/sun.security.krb5 \
+    java.security.jgss/sun.security.krb5:+open \
     java.security.jgss/sun.security.krb5.internal.crypto \
     java.security.jgss/sun.security.krb5.internal.ccache \
-    java.security.jgss/sun.security.krb5.internal \
+    java.security.jgss/sun.security.krb5.internal:+open \
     java.security.jgss/sun.security.krb5.internal.ktab \
     java.base/sun.security.util
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10BufferOverflowUnderflowTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10BufferOverflowUnderflowTest.java
index bcbdd75..be6601a 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10BufferOverflowUnderflowTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10BufferOverflowUnderflowTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10DataExchangeTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10DataExchangeTest.java
index 0a73dbf..95bf8ed 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10DataExchangeTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10DataExchangeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10EnginesClosureTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10EnginesClosureTest.java
index c84c364..7976c9d 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10EnginesClosureTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10EnginesClosureTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeTest.java
index 9ed88f6..d85d911 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeWithReplicatedPacketsTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeWithReplicatedPacketsTest.java
index 92b5dab..66bcc2e 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeWithReplicatedPacketsTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10HandshakeWithReplicatedPacketsTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon /javax/net/ssl/DTLS
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10IncorrectAppDataTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10IncorrectAppDataTest.java
index 43567e5..baec575 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10IncorrectAppDataTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10IncorrectAppDataTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon /javax/net/ssl/DTLS
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10MFLNTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10MFLNTest.java
index 61a3888..620ff49 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10MFLNTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10MFLNTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10NotEnabledRC4Test.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10NotEnabledRC4Test.java
index a4d4f43..3331675 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10NotEnabledRC4Test.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10NotEnabledRC4Test.java
@@ -27,10 +27,10 @@
  * @summary Testing DTLS engines do not enable RC4 ciphers by default.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0 DTLSv10NotEnabledRC4Test
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeTest.java
index 4af0fc0..3349cb6 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithCipherChangeTest.java
index 7677baa..f69afe6 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithCipherChangeTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithCipherChangeTest.java
@@ -29,10 +29,10 @@
  * @key randomness
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithDataExTest.java
index 560e924d..ccaefc4 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithDataExTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10RehandshakeWithDataExTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10SequenceNumberTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10SequenceNumberTest.java
index edf1436..ea70736 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10SequenceNumberTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10SequenceNumberTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon /javax/net/ssl/DTLS
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java
index 2d10634..685bac2 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/DTLSv10/DTLSv10UnsupportedCiphersTest.java
@@ -28,10 +28,10 @@
  *          causes IllegalArgumentException.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=DTLSv1.0
diff --git a/jdk/test/javax/net/ssl/DTLSv10/TEST.properties b/jdk/test/javax/net/ssl/DTLSv10/TEST.properties
index 080af05..7f6fae9 100644
--- a/jdk/test/javax/net/ssl/DTLSv10/TEST.properties
+++ b/jdk/test/javax/net/ssl/DTLSv10/TEST.properties
@@ -1,7 +1,7 @@
 modules = \
-    java.security.jgss/sun.security.krb5 \
+    java.security.jgss/sun.security.krb5:+open \
     java.security.jgss/sun.security.krb5.internal.crypto \
     java.security.jgss/sun.security.krb5.internal.ccache \
-    java.security.jgss/sun.security.krb5.internal \
+    java.security.jgss/sun.security.krb5.internal:+open \
     java.security.jgss/sun.security.krb5.internal.ktab \
     java.base/sun.security.util
diff --git a/jdk/test/javax/net/ssl/TLS/TEST.properties b/jdk/test/javax/net/ssl/TLS/TEST.properties
index 8c058b4..a007063 100644
--- a/jdk/test/javax/net/ssl/TLS/TEST.properties
+++ b/jdk/test/javax/net/ssl/TLS/TEST.properties
@@ -1,8 +1,8 @@
 modules = \
+    java.security.jgss/sun.security.krb5:+open \
     java.security.jgss/sun.security.krb5.internal.crypto \
     java.security.jgss/sun.security.krb5.internal.ktab \
-    java.security.jgss/sun.security.krb5 \
     java.security.jgss/sun.security.krb5.internal.ccache \
-    java.security.jgss/sun.security.krb5.internal \
+    java.security.jgss/sun.security.krb5.internal:+open \
     java.base/sun.security.util \
     jdk.crypto.ec/sun.security.ec
diff --git a/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java b/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java
index 0f51afd..674cf52 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSClientPropertyTest.java
@@ -28,11 +28,11 @@
  * @summary javax/net/ssl/TLS/TLSClientPropertyTest.java needs to be
  *     updated for JDK-8061210
  * @modules java.security.jgss
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm TLSClientPropertyTest NoProperty
  * @run main/othervm TLSClientPropertyTest SSLv3
diff --git a/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java b/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java
index 8a2957b..f226f52 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSDataExchangeTest.java
@@ -29,11 +29,11 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSDataExchangeTest
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSDataExchangeTest
diff --git a/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java
index 65d8d6c..e5c8db9 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSEnginesClosureTest.java
@@ -29,11 +29,11 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSEnginesClosureTest
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSEnginesClosureTest
diff --git a/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java b/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java
index 9b09fe2..19917c1 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSHandshakeTest.java
@@ -29,11 +29,11 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSHandshakeTest
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSHandshakeTest
diff --git a/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java b/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java
index edd8898..3b42c31 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSMFLNTest.java
@@ -30,11 +30,11 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSMFLNTest
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSMFLNTest
diff --git a/jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java b/jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java
index 38b7116..ad9b2fd 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSNotEnabledRC4Test.java
@@ -27,11 +27,11 @@
  * @summary Testing TLS engines do not enable RC4 ciphers by default.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS TLSNotEnabledRC4Test
  */
diff --git a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java
index 36be822..ef3f98f 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeTest.java
@@ -29,11 +29,11 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSRehandshakeTest
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSRehandshakeTest
diff --git a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java
index cc8fc79..8221c8d 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java
@@ -29,11 +29,11 @@
  * @key randomness
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS TLSRehandshakeWithCipherChangeTest
  */
diff --git a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java
index 0b277b2..d1e15cb 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSRehandshakeWithDataExTest.java
@@ -30,11 +30,11 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm TLSRehandshakeWithDataExTest
  * @run main/othervm -Dtest.security.protocol=TLS -Dtest.mode=norm_sni TLSRehandshakeWithDataExTest
diff --git a/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java
index 843f967..f915188 100644
--- a/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/TLS/TLSUnsupportedCiphersTest.java
@@ -28,11 +28,11 @@
  *          causes IllegalArgumentException.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
+ *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLS TLSUnsupportedCiphersTest
  */
diff --git a/jdk/test/javax/net/ssl/TLSv1/TEST.properties b/jdk/test/javax/net/ssl/TLSv1/TEST.properties
index 080af05..7f6fae9 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TEST.properties
+++ b/jdk/test/javax/net/ssl/TLSv1/TEST.properties
@@ -1,7 +1,7 @@
 modules = \
-    java.security.jgss/sun.security.krb5 \
+    java.security.jgss/sun.security.krb5:+open \
     java.security.jgss/sun.security.krb5.internal.crypto \
     java.security.jgss/sun.security.krb5.internal.ccache \
-    java.security.jgss/sun.security.krb5.internal \
+    java.security.jgss/sun.security.krb5.internal:+open \
     java.security.jgss/sun.security.krb5.internal.ktab \
     java.base/sun.security.util
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java
index 4e357e5..0d19c6b 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSDataExchangeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSDataExchangeTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java
index e0418c4..07db56a 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSEnginesClosureTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSEnginesClosureTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java
index bddcc18..a1a9bd3 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSHandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSHandshakeTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java
index 8b213eb..10d8cbf 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSMFLNTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSMFLNTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java b/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java
index 1a8f544..e6b1668 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSNotEnabledRC4Test.java
@@ -27,10 +27,10 @@
  * @summary Testing TLS engines do not enable RC4 ciphers by default.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 TLSNotEnabledRC4Test
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java
index 8208b6b..7f88052 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSRehandshakeTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java
index 3eb59d0..cdbc16f 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithCipherChangeTest.java
@@ -29,10 +29,10 @@
  * @key randomness
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 TLSRehandshakeWithCipherChangeTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java
index 17cce20..46b50da 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 -Dtest.mode=norm TLSRehandshakeWithDataExTest
diff --git a/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java
index 357b9e4..b3e3e60 100644
--- a/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/TLSv1/TLSUnsupportedCiphersTest.java
@@ -28,10 +28,10 @@
  *          causes IllegalArgumentException.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1 TLSUnsupportedCiphersTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java b/jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
index 3e86849..ca6b0d7 100644
--- a/jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
+++ b/jdk/test/javax/net/ssl/TLSv11/EmptyCertificateAuthorities.java
@@ -34,10 +34,10 @@
  * @summary Support TLS 1.1
  * @run main/othervm EmptyCertificateAuthorities
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @author Xuelei Fan
diff --git a/jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java b/jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java
index a8f9440..6ea71c0 100644
--- a/jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/ExportableBlockCipher.java
@@ -34,10 +34,10 @@
  * @summary Support TLS 1.1
  * @run main/othervm ExportableBlockCipher
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @author Xuelei Fan
diff --git a/jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java b/jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java
index 47939ec..df08c5d 100644
--- a/jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/ExportableStreamCipher.java
@@ -33,10 +33,10 @@
  * @bug 4873188
  * @summary Support TLS 1.1
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm ExportableStreamCipher
diff --git a/jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java b/jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java
index 067da2a..286992d 100644
--- a/jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/GenericBlockCipher.java
@@ -28,10 +28,10 @@
  * @bug 4873188
  * @summary Support TLS 1.1
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm GenericBlockCipher
diff --git a/jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java b/jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java
index e84f014..2c61321 100644
--- a/jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java
+++ b/jdk/test/javax/net/ssl/TLSv11/GenericStreamCipher.java
@@ -28,10 +28,10 @@
  * @bug 4873188
  * @summary Support TLS 1.1
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm GenericStreamCipher
diff --git a/jdk/test/javax/net/ssl/TLSv11/TEST.properties b/jdk/test/javax/net/ssl/TLSv11/TEST.properties
index 080af05..7f6fae9 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TEST.properties
+++ b/jdk/test/javax/net/ssl/TLSv11/TEST.properties
@@ -1,7 +1,7 @@
 modules = \
-    java.security.jgss/sun.security.krb5 \
+    java.security.jgss/sun.security.krb5:+open \
     java.security.jgss/sun.security.krb5.internal.crypto \
     java.security.jgss/sun.security.krb5.internal.ccache \
-    java.security.jgss/sun.security.krb5.internal \
+    java.security.jgss/sun.security.krb5.internal:+open \
     java.security.jgss/sun.security.krb5.internal.ktab \
     java.base/sun.security.util
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java
index fa3051f..7bb0abf 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSDataExchangeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSDataExchangeTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java
index d56b2c7..8c942c5 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSEnginesClosureTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSEnginesClosureTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java
index 437181e..390b480 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSHandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSHandshakeTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java
index 1a0abbb..f1dc84e 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSMFLNTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSMFLNTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java b/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java
index 629edfa..6dad7ac 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSNotEnabledRC4Test.java
@@ -27,10 +27,10 @@
  * @summary Testing TLS engines do not enable RC4 ciphers by default.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 TLSNotEnabledRC4Test
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java
index b4b2b78..ff18d91 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeTest.java
@@ -29,10 +29,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSRehandshakeTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java
index bd53715..c42454a 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithCipherChangeTest.java
@@ -29,10 +29,10 @@
  * @key randomness
  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 TLSRehandshakeWithCipherChangeTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java
index 43df7e9..73fc73c 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSRehandshakeWithDataExTest.java
@@ -30,10 +30,10 @@
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
  *          jdk.security.auth
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 -Dtest.mode=norm TLSRehandshakeWithDataExTest
diff --git a/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java b/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java
index afab2fd..7d270f5 100644
--- a/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java
+++ b/jdk/test/javax/net/ssl/TLSv11/TLSUnsupportedCiphersTest.java
@@ -28,10 +28,10 @@
  *          causes IllegalArgumentException.
  * @library /sun/security/krb5/auto /javax/net/ssl/TLSCommon
  * @modules java.security.jgss
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.crypto
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
  *          java.base/sun.security.util
  * @run main/othervm -Dtest.security.protocol=TLSv1.1 TLSUnsupportedCiphersTest
diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java
index d321952..1309d74 100644
--- a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java
+++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/ImplicitOpenClose.java
@@ -23,7 +23,7 @@
 
 /* @test
    @summary Test SoftSynthesizer implicit open/close using getReceiver.
-   @modules java.desktop/com.sun.media.sound
+   @modules java.desktop/com.sun.media.sound:+open
 */
 
 import java.lang.reflect.Field;
diff --git a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java
index 3ca088d..e3b2349 100644
--- a/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java
+++ b/jdk/test/javax/sound/midi/Gervill/SoftSynthesizer/Open.java
@@ -23,7 +23,7 @@
 
 /* @test
    @summary Test SoftSynthesizer open method
-   @modules java.desktop/com.sun.media.sound
+   @modules java.desktop/com.sun.media.sound:+open
 */
 
 import java.lang.reflect.Field;
diff --git a/jdk/test/javax/swing/JFileChooser/6688203/bug6688203.java b/jdk/test/javax/swing/JFileChooser/6688203/bug6688203.java
index 0b62dda..9f7e5d2 100644
--- a/jdk/test/javax/swing/JFileChooser/6688203/bug6688203.java
+++ b/jdk/test/javax/swing/JFileChooser/6688203/bug6688203.java
@@ -25,6 +25,7 @@
    @bug 6688203
    @summary Memory leak and performance problems in the method getFileSystemView of FileSystemView
    @author Pavel Porvatov
+   @modules java.desktop/javax.swing.filechooser:open
    @run main bug6688203
 */
 
diff --git a/jdk/test/javax/swing/JLabel/7004134/bug7004134.java b/jdk/test/javax/swing/JLabel/7004134/bug7004134.java
index 9440d14..7190dc9 100644
--- a/jdk/test/javax/swing/JLabel/7004134/bug7004134.java
+++ b/jdk/test/javax/swing/JLabel/7004134/bug7004134.java
@@ -28,6 +28,7 @@
  * @summary JLabel containing a ToolTipText does no longer show ToolTip after browser refresh
  * @author Pavel Porvatov
  * @modules java.desktop/sun.awt
+ * @modules java.desktop/javax.swing:open
  */
 
 import sun.awt.SunToolkit;
diff --git a/jdk/test/javax/swing/JPopupMenu/6495920/bug6495920.java b/jdk/test/javax/swing/JPopupMenu/6495920/bug6495920.java
index b15194a..6a8c132 100644
--- a/jdk/test/javax/swing/JPopupMenu/6495920/bug6495920.java
+++ b/jdk/test/javax/swing/JPopupMenu/6495920/bug6495920.java
@@ -30,6 +30,7 @@
  * @author Sergey Malenkov
  * @library ../..
  * @modules java.desktop/sun.awt
+ * @modules java.desktop/javax.swing.plaf.basic:open
  */
 
 import sun.awt.AppContext;
diff --git a/jdk/test/javax/swing/JPopupMenu/6800513/bug6800513.java b/jdk/test/javax/swing/JPopupMenu/6800513/bug6800513.java
index 098defe..4d16656 100644
--- a/jdk/test/javax/swing/JPopupMenu/6800513/bug6800513.java
+++ b/jdk/test/javax/swing/JPopupMenu/6800513/bug6800513.java
@@ -28,6 +28,7 @@
  * @bug 6800513
  * @summary GTK-LaF renders menus incompletely
  * @author Mario Torre
+ * @modules java.desktop/javax.swing:open
  * @library ../../regtesthelpers/
  * @build Util
  * @run main bug6800513
diff --git a/jdk/test/javax/swing/JSlider/6794836/bug6794836.java b/jdk/test/javax/swing/JSlider/6794836/bug6794836.java
index 0f4258d..5c84aa1 100644
--- a/jdk/test/javax/swing/JSlider/6794836/bug6794836.java
+++ b/jdk/test/javax/swing/JSlider/6794836/bug6794836.java
@@ -27,6 +27,7 @@
  * @bug 6794836
  * @summary BasicSliderUI throws NullPointerExc when JSlider maximum is Integer.MAX_VALUE
  * @author Pavel Porvatov
+ * @modules java.desktop/javax.swing.plaf.basic:open
  * @run main bug6794836
  */
 
diff --git a/jdk/test/javax/swing/JSlider/6848475/bug6848475.java b/jdk/test/javax/swing/JSlider/6848475/bug6848475.java
index e4f5bfcc..4fb81d3 100644
--- a/jdk/test/javax/swing/JSlider/6848475/bug6848475.java
+++ b/jdk/test/javax/swing/JSlider/6848475/bug6848475.java
@@ -27,6 +27,7 @@
  * @bug 6848475
  * @summary JSlider does not display the correct value of its BoundedRangeModel
  * @author Pavel Porvatov
+ * @modules java.desktop/javax.swing.plaf.basic:open
  * @run main bug6848475
  */
 
diff --git a/jdk/test/javax/swing/JTabbedPane/7010561/bug7010561.java b/jdk/test/javax/swing/JTabbedPane/7010561/bug7010561.java
index c79a398..16164ab 100644
--- a/jdk/test/javax/swing/JTabbedPane/7010561/bug7010561.java
+++ b/jdk/test/javax/swing/JTabbedPane/7010561/bug7010561.java
@@ -29,6 +29,7 @@
 /* @test
    @bug 7010561
    @summary Tab text position with Synth based LaF is different to Java 5/6
+   @modules java.desktop/javax.swing.plaf.basic:open
    @author Pavel Porvatov
 */
 public class bug7010561 {
diff --git a/jdk/test/javax/swing/JTree/6263446/bug6263446.java b/jdk/test/javax/swing/JTree/6263446/bug6263446.java
index 698255a..7094971 100644
--- a/jdk/test/javax/swing/JTree/6263446/bug6263446.java
+++ b/jdk/test/javax/swing/JTree/6263446/bug6263446.java
@@ -27,6 +27,7 @@
  * @bug 6263446
  * @summary Tests that double-clicking to edit a cell doesn't select the content.
  * @author Shannon Hickey
+ * @modules java.desktop/javax.swing.tree:open
  * @run main bug6263446
  */
 import java.awt.*;
diff --git a/jdk/test/javax/swing/RepaintManager/7013453/bug7013453.java b/jdk/test/javax/swing/RepaintManager/7013453/bug7013453.java
index 2314e3d..3a6c25f 100644
--- a/jdk/test/javax/swing/RepaintManager/7013453/bug7013453.java
+++ b/jdk/test/javax/swing/RepaintManager/7013453/bug7013453.java
@@ -24,6 +24,7 @@
 /* @test
    @bug 7013453
    @summary BufferStrategyPaintManager.dispose will cause IllegalMonitorStateException in event thread
+   @modules java.desktop/javax.swing:open
    @author Pavel Porvatov
 */
 
diff --git a/jdk/test/javax/swing/Security/6938813/bug6938813.java b/jdk/test/javax/swing/Security/6938813/bug6938813.java
index ba71ec9..21aed3f 100644
--- a/jdk/test/javax/swing/Security/6938813/bug6938813.java
+++ b/jdk/test/javax/swing/Security/6938813/bug6938813.java
@@ -26,6 +26,7 @@
  * @bug 6938813
  * @summary Swing mutable statics
  * @author Pavel Porvatov
+ * @modules java.desktop/javax.swing.text.html.parser:open
  * @modules java.desktop/sun.awt
  */
 
diff --git a/jdk/test/javax/swing/border/Test7149090.java b/jdk/test/javax/swing/border/Test7149090.java
index f93dc8e..11d33ec 100644
--- a/jdk/test/javax/swing/border/Test7149090.java
+++ b/jdk/test/javax/swing/border/Test7149090.java
@@ -24,6 +24,7 @@
 /* @test
    @bug 7149090
    @summary Nimbus:BorderFactory.createTitledBorder() the DEFAULT position of a title is not the same as the TOP
+   @modules java.desktop/javax.swing.border:open
    @author Pavel Porvatov
 */
 
diff --git a/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java b/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java
index be1b983..f1e1cbb 100644
--- a/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java
+++ b/jdk/test/javax/swing/plaf/synth/7143614/bug7143614.java
@@ -26,6 +26,7 @@
  * @bug 7143614
  * @summary Issues with Synth Look&Feel
  * @author Pavel Porvatov
+ * @modules java.desktop/javax.swing.plaf.synth:open
  * @modules java.desktop/sun.awt
  */
 
diff --git a/jdk/test/javax/swing/text/View/8014863/bug8014863.java b/jdk/test/javax/swing/text/View/8014863/bug8014863.java
index 9205349..30e54b6 100644
--- a/jdk/test/javax/swing/text/View/8014863/bug8014863.java
+++ b/jdk/test/javax/swing/text/View/8014863/bug8014863.java
@@ -28,6 +28,7 @@
  * @bug 8024395
  * @summary  Tests the calculation of the line breaks when a text is inserted
  * @author Dmitry Markov
+ * @modules java.desktop/javax.swing.text:open
  * @library ../../../regtesthelpers
  * @build Util
  * @run main bug8014863
diff --git a/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java b/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java
index daa9451..d5c3196 100644
--- a/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java
+++ b/jdk/test/javax/xml/jaxp/Encodings/CheckEncodingPropertiesFile.java
@@ -30,7 +30,7 @@
  *      correctly maps them to their preferred mime names.
  *      Also checks that the Encodings.properties resource file
  *      is consistent.
- * @modules java.xml/com.sun.org.apache.xml.internal.serializer
+ * @modules java.xml/com.sun.org.apache.xml.internal.serializer:+open
  * @compile -XDignore.symbol.file CheckEncodingPropertiesFile.java
  * @run main CheckEncodingPropertiesFile
  * @author Daniel Fuchs
diff --git a/jdk/test/javax/xml/jaxp/PrecisionDecimalDV/XPrecisionDecimalToString.java b/jdk/test/javax/xml/jaxp/PrecisionDecimalDV/XPrecisionDecimalToString.java
index 32254e4..015b49a 100644
--- a/jdk/test/javax/xml/jaxp/PrecisionDecimalDV/XPrecisionDecimalToString.java
+++ b/jdk/test/javax/xml/jaxp/PrecisionDecimalDV/XPrecisionDecimalToString.java
@@ -31,7 +31,7 @@
  *   in com.sun.org.apache.xerces.internal.impl.dv.xs.PrecisionDecimalDV$XPrecisionDecimal.
  *   Since that method is private the test unfortunately needs to use reflection
  *   to invoke the method.
- * @modules java.xml/com.sun.org.apache.xerces.internal.impl.dv.xs
+ * @modules java.xml/com.sun.org.apache.xerces.internal.impl.dv.xs:open
  * @run main XPrecisionDecimalToString
  * @author Daniel Fuchs
  */
diff --git a/jdk/test/jdk/internal/jline/console/StripAnsiTest.java b/jdk/test/jdk/internal/jline/console/StripAnsiTest.java
index 46f919e..7d13864 100644
--- a/jdk/test/jdk/internal/jline/console/StripAnsiTest.java
+++ b/jdk/test/jdk/internal/jline/console/StripAnsiTest.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8080679 8131913
  * @modules jdk.internal.le/jdk.internal.jline
- *          jdk.internal.le/jdk.internal.jline.console
+ *          jdk.internal.le/jdk.internal.jline.console:+open
  * @summary Verify ConsoleReader.stripAnsi strips escape sequences from its input correctly.
  */
 
diff --git a/jdk/test/jdk/internal/jrtfs/remote/Main.java b/jdk/test/jdk/internal/jrtfs/remote/Main.java
index 9b22c83..7242fa2 100644
--- a/jdk/test/jdk/internal/jrtfs/remote/Main.java
+++ b/jdk/test/jdk/internal/jrtfs/remote/Main.java
@@ -68,7 +68,7 @@
     }
 
     private static FileSystem createFsWithURLClassloader(String javaHome) throws IOException{
-        URL url = Paths.get(javaHome, "jrt-fs.jar").toUri().toURL();
+        URL url = Paths.get(javaHome, "lib", "jrt-fs.jar").toUri().toURL();
         URLClassLoader loader = new URLClassLoader(new URL[] { url });
         return FileSystems.newFileSystem(URI.create("jrt:/"),
                                                     Collections.emptyMap(),
diff --git a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java
index 7ea315a..cb0b041 100644
--- a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java
+++ b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java
@@ -64,7 +64,7 @@
         String java = jdk8Path.resolve("bin/java").toAbsolutePath().toString();
         String javac = jdk8Path.resolve("bin/javac").toAbsolutePath().toString();
         Files.createDirectories(Paths.get(".", CLASSES_DIR));
-        String jrtJar = Paths.get(TEST_JAVAHOME, JRTFS_JAR).toAbsolutePath().toString();
+        String jrtJar = Paths.get(TEST_JAVAHOME, "lib", JRTFS_JAR).toAbsolutePath().toString();
 
         // Compose command-lines for compiling and executing tests
         List<List<String>> cmds = Arrays.asList(
diff --git a/jdk/test/jdk/internal/misc/Unsafe/CopyCommon.java b/jdk/test/jdk/internal/misc/Unsafe/CopyCommon.java
index 65e2b58..2d575be 100644
--- a/jdk/test/jdk/internal/misc/Unsafe/CopyCommon.java
+++ b/jdk/test/jdk/internal/misc/Unsafe/CopyCommon.java
@@ -22,7 +22,6 @@
  */
 
 import jdk.internal.misc.Unsafe;
-import java.lang.reflect.Field;
 
 /**
  * Helper class to support testing of Unsafe.copyMemory and Unsafe.copySwapMemory
@@ -37,17 +36,7 @@
     static final int SMALL_COPY_SIZE = 32;
     static final int BASE_ALIGNMENT = 16;
 
-    protected static final Unsafe UNSAFE;
-
-    static {
-        try {
-            Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
-            f.setAccessible(true);
-            UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to get Unsafe instance.", e);
-        }
-    }
+    protected static final Unsafe UNSAFE = Unsafe.getUnsafe();
 
     static long alignDown(long value, long alignment) {
         return value & ~(alignment - 1);
diff --git a/jdk/test/jdk/internal/reflect/CallerSensitive/CallerSensitiveFinder.java b/jdk/test/jdk/internal/reflect/CallerSensitive/CallerSensitiveFinder.java
index 2be9c57..ab573e3 100644
--- a/jdk/test/jdk/internal/reflect/CallerSensitive/CallerSensitiveFinder.java
+++ b/jdk/test/jdk/internal/reflect/CallerSensitive/CallerSensitiveFinder.java
@@ -152,6 +152,9 @@
         try {
             ClassFileReader reader = ClassFileReader.newInstance(path);
             for (ClassFile cf : reader.getClassFiles()) {
+                if (cf.access_flags.is(AccessFlags.ACC_MODULE))
+                    continue;
+
                 String classFileName = cf.getName();
                 // for each ClassFile
                 //    parse constant pool to find matching method refs
diff --git a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java
index a0a32fc..cd25a49 100644
--- a/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java
+++ b/jdk/test/jdk/modules/etc/VerifyModuleDelegation.java
@@ -50,15 +50,15 @@
     private static final String JAVA_COMPACT2 = "java.compact2";
 
     private static final ModuleDescriptor BASE
-        = new ModuleDescriptor.Builder(JAVA_BASE).build();
+        = ModuleDescriptor.module(JAVA_BASE).build();
 
     private static final ModuleDescriptor COMPACT2
-        = new ModuleDescriptor.Builder(JAVA_COMPACT2)
+        = ModuleDescriptor.module(JAVA_COMPACT2)
             .requires(Set.of(MANDATED), JAVA_BASE)
-            .requires(Set.of(PUBLIC), JAVA_COMPACT1)
-            .requires(Set.of(PUBLIC), "java.rmi")
-            .requires(Set.of(PUBLIC), "java.sql")
-            .requires(Set.of(PUBLIC), "java.xml")
+            .requires(Set.of(TRANSITIVE), JAVA_COMPACT1)
+            .requires(Set.of(TRANSITIVE), "java.rmi")
+            .requires(Set.of(TRANSITIVE), "java.sql")
+            .requires(Set.of(TRANSITIVE), "java.xml")
             .build();
 
     private static final Set<ModuleDescriptor> MREFS
diff --git a/jdk/test/jdk/modules/open/Basic.java b/jdk/test/jdk/modules/open/Basic.java
new file mode 100644
index 0000000..2af576e
--- /dev/null
+++ b/jdk/test/jdk/modules/open/Basic.java
@@ -0,0 +1,317 @@
+/*
+ * 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
+ * @library modules
+ * @build m1/* m2/*
+ * @run testng/othervm --add-modules=m1,m2 Basic
+ * @summary Basic test of open modules and open packages
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InaccessibleObjectException;
+import java.lang.reflect.Module;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeTest;
+import static org.testng.Assert.*;
+
+/**
+ * open module m1 {
+ *     exports p;
+ *     // contains p.internal
+ * }
+ *
+ * module m2 {
+ *     exports q;
+ *     exports q;
+ *     // contains q.internal
+ * }
+ *
+ * Each package in m1 and m2 contains a public type a non-public type.
+ */
+
+public class Basic {
+
+    @BeforeTest
+    public void checkSetup() throws Exception {
+        Module m1 = Class.forName("p.PublicType").getModule();
+        assertTrue(m1.isNamed());
+        assertTrue(m1.getDescriptor().isOpen());
+        assertTrue(m1.getDescriptor().packages().size() == 2);
+        assertTrue(m1.getDescriptor().packages().contains("p"));
+        assertTrue(m1.getDescriptor().packages().contains("p.internal"));
+        assertTrue(m1.getDescriptor().exports().size() == 1);
+        ModuleDescriptor.Exports e = m1.getDescriptor().exports().iterator().next();
+        assertTrue(e.source().equals("p"));
+        assertTrue(m1.isOpen("p"));
+        assertTrue(m1.isOpen("p.internal"));
+
+        Module m2 = Class.forName("q.PublicType").getModule();
+        assertTrue(m2.isNamed());
+        assertFalse(m2.getDescriptor().isOpen());
+        assertTrue(m2.getDescriptor().packages().size() == 2);
+        assertTrue(m2.getDescriptor().packages().contains("q"));
+        assertTrue(m2.getDescriptor().packages().contains("q.internal"));
+        assertTrue(m2.getDescriptor().exports().size() == 1);
+        e = m2.getDescriptor().exports().iterator().next();
+        assertTrue(e.source().equals("q"));
+        assertTrue(m2.isOpen("q"));
+        assertFalse(m2.isOpen("p.internal"));
+    }
+
+    @Test
+    public void testPublicTypeInExportedPackage() throws Throwable {
+        // invokespecial
+        new p.PublicType();
+
+        Class<?> clazz = p.PublicType.class;
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        ctor.newInstance();
+        ctor.setAccessible(true);
+        ctor.newInstance();
+
+        // method handles
+        findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+        findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        findNoArgConstructorAndInvoke(clazz, lookup);
+    }
+
+    @Test
+    public void testNotPublicTypeInExportedPackage() throws Throwable {
+        Class<?> clazz = Class.forName("p.NotPublicType");
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        try {
+            ctor.newInstance();
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        ctor.setAccessible(true);
+        ctor.newInstance();
+
+        // method handles
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        findNoArgConstructorAndInvoke(clazz, lookup);
+    }
+
+    @Test
+    public void testPublicTypeInNonExportedPackage() throws Throwable {
+        Class<?> clazz = Class.forName("p.internal.PublicType");
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        ctor.newInstance(); // should succeed
+        ctor.setAccessible(true);
+        ctor.newInstance();
+
+        // method handles
+        findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+        findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        findNoArgConstructorAndInvoke(clazz, lookup);
+    }
+
+    @Test
+    public void testNotPublicTypeInNonExportedPackage() throws Throwable {
+        Class<?> clazz = Class.forName("p.internal.NotPublicType");
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        try {
+            ctor.newInstance();
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        ctor.setAccessible(true);
+        ctor.newInstance();
+
+        // method handles
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        findNoArgConstructorAndInvoke(clazz, lookup);
+    }
+
+    @Test
+    public void testPublicTypeInOpenPackage() throws Throwable {
+        // invokespecial
+        // new q.PublicType();   TBD
+
+        // core reflection
+        Class<?> clazz = q.PublicType.class;
+        clazz.getConstructor().newInstance();
+
+        // method handles
+        findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+        findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        findNoArgConstructorAndInvoke(clazz, lookup);
+
+    }
+
+    @Test
+    public void testNotPublicTypeInOpenPackage() throws Throwable {
+        Class<?> clazz = Class.forName("q.NotPublicType");
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        try {
+            ctor.newInstance();
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        ctor.setAccessible(true);
+        ctor.newInstance();
+
+        // method handles
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+        } catch (IllegalAccessException expected) { }
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        Lookup lookup = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+        findNoArgConstructorAndInvoke(clazz, lookup);
+    }
+
+    @Test
+    public void testPublicTypeInConcealedPackage() throws Throwable {
+        Class<?> clazz = Class.forName("q.internal.PublicType");
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        try {
+            ctor.newInstance();
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            ctor.setAccessible(true);
+            assertTrue(false);
+        } catch (InaccessibleObjectException expected) { }
+
+        // method handles
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+        } catch (IllegalAccessException expected) { }
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+    }
+
+    @Test
+    public void testNotPublicTypeInConcealedPackage() throws Throwable {
+        Class<?> clazz = Class.forName("q.internal.NotPublicType");
+
+        // core reflection
+        Constructor<?> ctor = clazz.getConstructor();
+        try {
+            ctor.newInstance();
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            ctor.setAccessible(true);
+            assertTrue(false);
+        } catch (InaccessibleObjectException expected) { }
+
+        // method handles
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.publicLookup());
+        } catch (IllegalAccessException expected) { }
+        try {
+            findNoArgConstructorAndInvoke(clazz, MethodHandles.lookup());
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.publicLookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+        try {
+            MethodHandles.privateLookupIn(clazz, MethodHandles.lookup());
+            assertTrue(false);
+        } catch (IllegalAccessException expected) { }
+    }
+
+    /**
+     * Produces the method handle for the no-arg constructor and invokes it
+     */
+    Object findNoArgConstructorAndInvoke(Class<?> clazz, Lookup lookup) throws Throwable {
+        MethodType mt = MethodType.methodType(void.class);
+        MethodHandle mh = lookup.findConstructor(clazz, mt);
+        return mh.invoke();
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m1/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m1/module-info.java
index 9d2c8be..222a167 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m1/module-info.java
@@ -20,8 +20,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-module m1 {
-    requires unsupported;
-    exports p1;
+open module m1 {
+    exports p;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m1/p/NotPublicType.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m1/p/NotPublicType.java
index 9d2c8be..ab6a417 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m1/p/NotPublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class NotPublicType {
+    public NotPublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m1/p/PublicType.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m1/p/PublicType.java
index 9d2c8be..77ab58e 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m1/p/PublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+public class PublicType {
+    public PublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m1/p/internal/NotPublicType.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m1/p/internal/NotPublicType.java
index 9d2c8be..2509f4e 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m1/p/internal/NotPublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p.internal;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class NotPublicType {
+    public NotPublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m1/p/internal/PublicType.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m1/p/internal/PublicType.java
index 9d2c8be..0f62023 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m1/p/internal/PublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package p.internal;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+public class PublicType {
+    public PublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m2/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m2/module-info.java
index 9d2c8be..a55d4f5 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m2/module-info.java
@@ -20,8 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-module m1 {
-    requires unsupported;
-    exports p1;
+module m2 {
+    exports q;
+    opens q;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m2/q/NotPublicType.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m2/q/NotPublicType.java
index 9d2c8be..43f252b 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m2/q/NotPublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package q;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class NotPublicType {
+    public NotPublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m2/q/PublicType.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m2/q/PublicType.java
index 9d2c8be..4a14f4b 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m2/q/PublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package q;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+public class PublicType {
+    public PublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m2/q/internal/NotPublicType.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m2/q/internal/NotPublicType.java
index 9d2c8be..4ddfe29 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m2/q/internal/NotPublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package q.internal;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+class NotPublicType {
+    public NotPublicType() { }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/jdk/modules/open/modules/m2/q/internal/PublicType.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/jdk/modules/open/modules/m2/q/internal/PublicType.java
index 9d2c8be..a7df382 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/jdk/modules/open/modules/m2/q/internal/PublicType.java
@@ -20,8 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+package q.internal;
 
-module m1 {
-    requires unsupported;
-    exports p1;
+public class PublicType {
+    public PublicType() { }
 }
diff --git a/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/test/Main.java b/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/test/Main.java
index 05ff04d..5897d67 100644
--- a/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/test/Main.java
+++ b/jdk/test/jdk/modules/scenarios/automaticmodules/src/sptest/test/Main.java
@@ -58,10 +58,10 @@
         assertTrue(requires.contains("java.base"));
 
         // uses ScriptEngineFactory
-        Map<String, Provides> provides = descriptor.provides();
+        Set<Provides> provides = descriptor.provides();
         assertTrue(provides.size() == 1);
         String sn = ScriptEngineFactory.class.getName();
-        assertTrue(provides.containsKey(sn));
+        assertTrue(provides.iterator().next().service().equals(sn));
 
         // Check that it is iterated over with ServiceLoader
         ServiceLoader<ScriptEngineFactory> sl
diff --git a/jdk/test/sun/net/idn/TestStringPrep.java b/jdk/test/sun/net/idn/TestStringPrep.java
index 493d4bf..95340ae 100644
--- a/jdk/test/sun/net/idn/TestStringPrep.java
+++ b/jdk/test/sun/net/idn/TestStringPrep.java
@@ -25,7 +25,8 @@
  * @test
  * @summary Unit test for sun.net.idn.Punycode
  * @bug 4737170 8060097
- * @modules java.base/sun.net.idn java.base/sun.text.normalizer
+ * @modules java.base/sun.net.idn:+open
+ *          java.base/sun.text.normalizer
  * @library .
  * @compile -XDignore.symbol.file TestStringPrep.java NFS4StringPrep.java
  *     TestData.java
diff --git a/jdk/test/sun/net/www/http/HttpClient/IsAvailable.java b/jdk/test/sun/net/www/http/HttpClient/IsAvailable.java
index 8a509cb..4396e0e 100644
--- a/jdk/test/sun/net/www/http/HttpClient/IsAvailable.java
+++ b/jdk/test/sun/net/www/http/HttpClient/IsAvailable.java
@@ -27,7 +27,7 @@
  * @summary HttpClient available() check throws SocketException when connection
  * has been closed
  * @modules java.base/sun.net
- *          java.base/sun.net.www.http
+ *          java.base/sun.net.www.http:+open
  */
 
 import java.net.URL;
diff --git a/jdk/test/sun/net/www/httptest/TestHttpServer.java b/jdk/test/sun/net/www/httptest/TestHttpServer.java
index 13f2098..543e7c0 100644
--- a/jdk/test/sun/net/www/httptest/TestHttpServer.java
+++ b/jdk/test/sun/net/www/httptest/TestHttpServer.java
@@ -116,15 +116,26 @@
         }
     }
 
-    /** Tell all threads in the server to exit within 5 seconds.
-     *  This is an abortive termination. Just prior to the thread exiting
-     *  all channels in that thread waiting to be closed are forceably closed.
+    /**
+     * Tell all threads in the server to exit within 5 seconds.
+     * This is an abortive termination. Just prior to the thread exiting
+     * all channels in that thread waiting to be closed are forceably closed.
+     * @throws InterruptedException
      */
 
     public void terminate () {
         for (int i=0; i<threads; i++) {
             servers[i].terminate ();
         }
+
+        for (int i = 0; i < threads; i++) {
+            try {
+                servers[i].join();
+            } catch (InterruptedException e) {
+                System.err.println("Unexpected InterruptedException during terminating server");
+                throw new RuntimeException(e);
+            }
+        }
     }
 
     /**
@@ -147,7 +158,7 @@
         int maxconn;
         int nconn;
         ClosedChannelList clist;
-        boolean shutdown;
+        volatile boolean shutdown;
 
         Server (HttpCallback cb, ServerSocketChannel schan, int maxconn) {
             this.schan = schan;
@@ -166,18 +177,18 @@
         }
 
         /* Stop the thread as soon as possible */
-        public synchronized void terminate () {
+        public void terminate () {
             shutdown = true;
         }
 
         public void run ()  {
             try {
                 while (true) {
-                    selector.select (1000);
-                    Set selected = selector.selectedKeys();
-                    Iterator iter = selected.iterator();
+                    selector.select(1000);
+                    Set<SelectionKey> selected = selector.selectedKeys();
+                    Iterator<SelectionKey> iter = selected.iterator();
                     while (iter.hasNext()) {
-                        key = (SelectionKey)iter.next();
+                        key = iter.next();
                         if (key.equals (listenerKey)) {
                             SocketChannel sock = schan.accept ();
                             if (sock == null) {
@@ -200,7 +211,7 @@
                                 SocketChannel chan = (SocketChannel) key.channel();
                                 System.out.println("SERVER: connection readable. chan[" + chan + "]");
                                 if (key.attachment() != null) {
-                                    System.out.println("Server: comsume");
+                                    System.out.println("Server: consume");
                                     closed = consume (chan);
                                 } else {
                                     closed = read (chan, key);
@@ -219,7 +230,16 @@
                     }
                     clist.check();
                     if (shutdown) {
+                        System.out.println("Force to Shutdown");
+                        SelectionKey sKey = schan.keyFor(selector);
+                        if (sKey != null) {
+                            sKey.cancel();
+                        }
+
                         clist.terminate ();
+                        selector.close();
+                        schan.socket().close();
+                        schan.close();
                         return;
                     }
                 }
@@ -726,3 +746,4 @@
         }
     }
 }
+
diff --git a/jdk/test/sun/net/www/protocol/http/NoNTLM.java b/jdk/test/sun/net/www/protocol/http/NoNTLM.java
index a0b74a3..cc71619 100644
--- a/jdk/test/sun/net/www/protocol/http/NoNTLM.java
+++ b/jdk/test/sun/net/www/protocol/http/NoNTLM.java
@@ -26,7 +26,7 @@
  * @summary Sanity check that NTLM will not be selected by the http protocol
  *    handler when running on a profile that does not support NTLM
  * @modules java.base/sun.net.www
- *          java.base/sun.net.www.protocol.http
+ *          java.base/sun.net.www.protocol.http:open
  * @run main/othervm NoNTLM
  */
 
diff --git a/jdk/test/sun/security/jgss/spnego/NotPreferredMech.java b/jdk/test/sun/security/jgss/spnego/NotPreferredMech.java
index bbe5024..d057e95 100644
--- a/jdk/test/sun/security/jgss/spnego/NotPreferredMech.java
+++ b/jdk/test/sun/security/jgss/spnego/NotPreferredMech.java
@@ -26,7 +26,7 @@
  * @bug 8048194
  * @modules java.base/sun.security.util
  *          java.security.jgss/sun.security.jgss
- *          java.security.jgss/sun.security.jgss.spnego
+ *          java.security.jgss/sun.security.jgss.spnego:+open
  * @run main/othervm NotPreferredMech
  * @summary GSSContext.acceptSecContext fails when a supported mech is not initiator preferred
  */
diff --git a/jdk/test/sun/security/krb5/RFC396xTest.java b/jdk/test/sun/security/krb5/RFC396xTest.java
index 186a624..18814ac 100644
--- a/jdk/test/sun/security/krb5/RFC396xTest.java
+++ b/jdk/test/sun/security/krb5/RFC396xTest.java
@@ -25,7 +25,7 @@
  * @bug 6862679
  * @modules java.security.jgss/sun.security.krb5
  *          java.security.jgss/sun.security.krb5.internal.crypto
- *          java.security.jgss/sun.security.krb5.internal.crypto.dk
+ *          java.security.jgss/sun.security.krb5.internal.crypto.dk:+open
  * @run main/othervm RFC396xTest
  * @summary ESC: AD Authentication with user with umlauts fails
  */
diff --git a/jdk/test/sun/security/krb5/auto/Renew.java b/jdk/test/sun/security/krb5/auto/Renew.java
index f6c8932..41e3fcd 100644
--- a/jdk/test/sun/security/krb5/auto/Renew.java
+++ b/jdk/test/sun/security/krb5/auto/Renew.java
@@ -27,8 +27,8 @@
  * @summary JAAS Krb5LoginModule has suspect ticket-renewal logic,
  *          relies on clockskew grace
  * @modules java.base/sun.security.util
- *          java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal
+ *          java.security.jgss/sun.security.krb5:+open
+ *          java.security.jgss/sun.security.krb5.internal:+open
  *          java.security.jgss/sun.security.krb5.internal.ccache
  *          java.security.jgss/sun.security.krb5.internal.crypto
  *          java.security.jgss/sun.security.krb5.internal.ktab
diff --git a/jdk/test/sun/security/krb5/auto/TEST.properties b/jdk/test/sun/security/krb5/auto/TEST.properties
index 35a55e5..777c20d 100644
--- a/jdk/test/sun/security/krb5/auto/TEST.properties
+++ b/jdk/test/sun/security/krb5/auto/TEST.properties
@@ -1,8 +1,8 @@
 modules java.base/jdk.internal.misc \
         java.base/sun.security.util \
         java.security.jgss/sun.security.jgss \
-        java.security.jgss/sun.security.krb5 \
-        java.security.jgss/sun.security.krb5.internal \
+        java.security.jgss/sun.security.krb5:+open \
+        java.security.jgss/sun.security.krb5.internal:+open \
         java.security.jgss/sun.security.krb5.internal.ccache \
         java.security.jgss/sun.security.krb5.internal.rcache \
         java.security.jgss/sun.security.krb5.internal.crypto \
diff --git a/jdk/test/sun/security/krb5/ccache/TimeInCCache.java b/jdk/test/sun/security/krb5/ccache/TimeInCCache.java
index 5a9364f..e88c6b0 100644
--- a/jdk/test/sun/security/krb5/ccache/TimeInCCache.java
+++ b/jdk/test/sun/security/krb5/ccache/TimeInCCache.java
@@ -24,7 +24,7 @@
  * @test
  * @bug 6590930
  * @modules java.security.jgss/sun.security.krb5
- *          java.security.jgss/sun.security.krb5.internal.ccache
+ *          java.security.jgss/sun.security.krb5.internal.ccache:+open
  * @run main/othervm TimeInCCache
  * @summary read/write does not match for ccache
  */
diff --git a/jdk/test/sun/security/krb5/config/DefUdpLimit.java b/jdk/test/sun/security/krb5/config/DefUdpLimit.java
index 58c6c6d..0674f24 100644
--- a/jdk/test/sun/security/krb5/config/DefUdpLimit.java
+++ b/jdk/test/sun/security/krb5/config/DefUdpLimit.java
@@ -25,8 +25,7 @@
  * @test
  * @bug 8009875
  * @summary Provide a default udp_preference_limit for krb5.conf
- * @modules java.security.jgss/sun.security.krb5
- * @compile -XDignore.symbol.file DefUdpLimit.java
+ * @modules java.security.jgss/sun.security.krb5:+open
  * @run main/othervm DefUdpLimit -1 1465
  * @run main/othervm DefUdpLimit 0 0
  * @run main/othervm DefUdpLimit 1234 1234
diff --git a/jdk/test/sun/security/krb5/config/DnsFallback.java b/jdk/test/sun/security/krb5/config/DnsFallback.java
index 1def972..57ecafe 100644
--- a/jdk/test/sun/security/krb5/config/DnsFallback.java
+++ b/jdk/test/sun/security/krb5/config/DnsFallback.java
@@ -23,7 +23,7 @@
 /*
  * @test
  * @bug 6673164 6552334 8077102
- * @modules java.security.jgss/sun.security.krb5
+ * @modules java.security.jgss/sun.security.krb5:+open
  * @run main/othervm DnsFallback
  * @summary fix dns_fallback parse error, and use dns by default
  */
diff --git a/jdk/test/sun/security/krb5/config/SCDynamicConfigTest.java b/jdk/test/sun/security/krb5/config/SCDynamicConfigTest.java
index 40ec7d6..c8dd064 100644
--- a/jdk/test/sun/security/krb5/config/SCDynamicConfigTest.java
+++ b/jdk/test/sun/security/krb5/config/SCDynamicConfigTest.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 7184246
  * @summary Simplify Config.get() of krb5
- * @modules java.security.jgss/sun.security.krb5
+ * @modules java.security.jgss/sun.security.krb5:+open
  */
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
diff --git a/jdk/test/sun/security/krb5/tools/KtabZero.java b/jdk/test/sun/security/krb5/tools/KtabZero.java
index 6cc2a52..3f4246e 100644
--- a/jdk/test/sun/security/krb5/tools/KtabZero.java
+++ b/jdk/test/sun/security/krb5/tools/KtabZero.java
@@ -34,7 +34,7 @@
  * @bug 8014196
  * @summary ktab creates a file with zero kt_vno
  * @requires os.family == "windows"
- * @modules java.security.jgss/sun.security.krb5.internal.ktab
+ * @modules java.security.jgss/sun.security.krb5.internal.ktab:+open
  *          java.security.jgss/sun.security.krb5.internal.tools
  */
 public class KtabZero {
diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java
index 1724fd3..7b23e80 100644
--- a/jdk/test/sun/security/pkcs11/PKCS11Test.java
+++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java
@@ -642,6 +642,8 @@
     static final boolean badNSSVersion =
             getNSSVersion() >= 3.11 && getNSSVersion() < 3.12;
 
+    private static final String distro = distro();
+
     static final boolean badSolarisSparc =
             System.getProperty("os.name").equals("SunOS") &&
             System.getProperty("os.arch").equals("sparcv9") &&
@@ -735,13 +737,17 @@
      * Get the identifier for the operating system distribution
      */
     static String getDistro() {
+        return distro;
+    }
+
+    private static String distro() {
         try (BufferedReader in =
             new BufferedReader(new InputStreamReader(
                 Runtime.getRuntime().exec("uname -v").getInputStream()))) {
 
             return in.readLine();
         } catch (Exception e) {
-            return "";
+            throw new RuntimeException("Failed to determine distro.", e);
         }
     }
 
diff --git a/jdk/test/sun/security/provider/FileInputStreamPool/FileInputStreamPoolTest.java b/jdk/test/sun/security/provider/FileInputStreamPool/FileInputStreamPoolTest.java
index 55811dd..e7fafc1 100644
--- a/jdk/test/sun/security/provider/FileInputStreamPool/FileInputStreamPoolTest.java
+++ b/jdk/test/sun/security/provider/FileInputStreamPool/FileInputStreamPoolTest.java
@@ -24,7 +24,8 @@
 /**
  * @test
  * @bug 8047769
- * @modules java.base/sun.security.provider
+ * @modules java.base/java.lang.ref:open
+ *          java.base/sun.security.provider:open
  * @summary SecureRandom should be more frugal with file descriptors
  */
 
diff --git a/jdk/test/sun/security/provider/SecureRandom/CommonSeeder.java b/jdk/test/sun/security/provider/SecureRandom/CommonSeeder.java
index 22f1f0c..8908149 100644
--- a/jdk/test/sun/security/provider/SecureRandom/CommonSeeder.java
+++ b/jdk/test/sun/security/provider/SecureRandom/CommonSeeder.java
@@ -33,7 +33,8 @@
 /**
  * @test
  * @bug 8051408
- * @modules java.base/sun.security.provider
+ * @modules java.base/java.lang.reflect:open
+ *          java.base/sun.security.provider:+open
  * @run main/othervm CommonSeeder
  * @summary check entropy reading of DRBGs
  */
diff --git a/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java b/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java
index aaf005d..410bf0c 100644
--- a/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java
+++ b/jdk/test/sun/security/provider/SecureRandom/DRBGS11n.java
@@ -32,7 +32,7 @@
 /**
  * @test
  * @bug 8157308
- * @modules java.base/sun.security.provider
+ * @modules java.base/sun.security.provider:+open
  * @summary Make AbstractDrbg non-Serializable
  * @run main DRBGS11n mech
  * @run main DRBGS11n capability
diff --git a/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java b/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java
index d6b5280..89c50b2 100644
--- a/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java
+++ b/jdk/test/sun/security/ssl/ExtensionType/OptimalListSize.java
@@ -26,7 +26,8 @@
  * @bug 8080535
  * @summary Expected size of Character.UnicodeBlock.map is not optimal
  * @library /lib/testlibrary
- * @modules java.base/sun.security.ssl
+ * @modules java.base/java.util:open
+ *          java.base/sun.security.ssl:open
  * @build jdk.testlibrary.OptimalCapacity
  * @run main OptimalListSize
  */
diff --git a/jdk/test/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java b/jdk/test/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
index 8a5db10..1cf22f0 100644
--- a/jdk/test/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
+++ b/jdk/test/sun/security/ssl/X509TrustManagerImpl/PKIXExtendedTM.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,9 +28,12 @@
 
 /*
  * @test
- * @bug 6916074
+ * @bug 6916074 8170131
  * @summary Add support for TLS 1.2
- * @run main/othervm PKIXExtendedTM
+ * @run main/othervm PKIXExtendedTM 0
+ * @run main/othervm PKIXExtendedTM 1
+ * @run main/othervm PKIXExtendedTM 2
+ * @run main/othervm PKIXExtendedTM 3
  */
 
 import java.net.*;
@@ -42,6 +45,7 @@
 import java.security.KeyFactory;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathValidatorException;
 import java.security.spec.*;
 import java.security.interfaces.*;
 import java.math.BigInteger;
@@ -792,20 +796,85 @@
     volatile Exception serverException = null;
     volatile Exception clientException = null;
 
-    public static void main(String args[]) throws Exception {
-        // MD5 is used in this test case, don't disable MD5 algorithm.
-        Security.setProperty("jdk.certpath.disabledAlgorithms",
-                "MD2, RSA keySize < 1024");
-        Security.setProperty("jdk.tls.disabledAlgorithms",
-                "SSLv3, RC4, DH keySize < 768");
+    static class Test {
+        String tlsDisAlgs;
+        String certPathDisAlgs;
+        boolean fail;
+        Test(String tlsDisAlgs, String certPathDisAlgs, boolean fail) {
+            this.tlsDisAlgs = tlsDisAlgs;
+            this.certPathDisAlgs = certPathDisAlgs;
+            this.fail = fail;
+        }
+    }
 
-        if (debug)
+    static Test[] tests = {
+        // MD5 is used in this test case, don't disable MD5 algorithm.
+        new Test(
+            "SSLv3, RC4, DH keySize < 768",
+            "MD2, RSA keySize < 1024",
+            false),
+        // Disable MD5 but only if cert chains back to public root CA, should
+        // pass because the MD5 cert in this test case is issued by test CA
+        new Test(
+            "SSLv3, RC4, DH keySize < 768",
+            "MD2, MD5 jdkCA, RSA keySize < 1024",
+            false),
+        // Disable MD5 alg via TLS property and expect failure
+        new Test(
+            "SSLv3, MD5, RC4, DH keySize < 768",
+            "MD2, RSA keySize < 1024",
+            true),
+        // Disable MD5 alg via certpath property and expect failure
+        new Test(
+            "SSLv3, RC4, DH keySize < 768",
+            "MD2, MD5, RSA keySize < 1024",
+            true),
+    };
+
+    public static void main(String args[]) throws Exception {
+        if (args.length != 1) {
+            throw new Exception("Incorrect number of arguments");
+        }
+        Test test = tests[Integer.parseInt(args[0])];
+        Security.setProperty("jdk.tls.disabledAlgorithms", test.tlsDisAlgs);
+        Security.setProperty("jdk.certpath.disabledAlgorithms",
+                             test.certPathDisAlgs);
+
+        if (debug) {
             System.setProperty("javax.net.debug", "all");
+        }
 
         /*
          * Start the tests.
          */
-        new PKIXExtendedTM();
+        try {
+            new PKIXExtendedTM();
+            if (test.fail) {
+                throw new Exception("Expected MD5 certificate to be blocked");
+            }
+        } catch (Exception e) {
+            if (test.fail) {
+                // find expected cause
+                boolean correctReason = false;
+                Throwable cause = e.getCause();
+                while (cause != null) {
+                    if (cause instanceof CertPathValidatorException) {
+                        CertPathValidatorException cpve =
+                            (CertPathValidatorException)cause;
+                        if (cpve.getReason() == CertPathValidatorException.BasicReason.ALGORITHM_CONSTRAINED) {
+                            correctReason = true;
+                            break;
+                        }
+                    }
+                    cause = cause.getCause();
+                }
+                if (!correctReason) {
+                    throw new Exception("Unexpected exception", e);
+                }
+            } else {
+                throw e;
+            }
+        }
     }
 
     Thread clientThread = null;
diff --git a/jdk/test/sun/security/tools/jarsigner/LargeJarEntry.java b/jdk/test/sun/security/tools/jarsigner/LargeJarEntry.java
index c108350..c071240 100644
--- a/jdk/test/sun/security/tools/jarsigner/LargeJarEntry.java
+++ b/jdk/test/sun/security/tools/jarsigner/LargeJarEntry.java
@@ -27,7 +27,7 @@
  * @summary Make sure jar files with large entries (more than max heap size)
  *    can be signed
  * @modules jdk.jartool/sun.security.tools.jarsigner
- * @run main/othervm -Xmx8M LargeJarEntry
+ * @run main/othervm -Xmx16m LargeJarEntry
  * @author Sean Mullan
  */
 
diff --git a/jdk/test/sun/security/tools/keytool/StartDateTest.java b/jdk/test/sun/security/tools/keytool/StartDateTest.java
index d558ff6..64f8860 100644
--- a/jdk/test/sun/security/tools/keytool/StartDateTest.java
+++ b/jdk/test/sun/security/tools/keytool/StartDateTest.java
@@ -25,8 +25,7 @@
  * @test
  * @bug 6468285
  * @summary keytool ability to backdate self-signed certificates to compensate for clock skew
- * @modules java.base/sun.security.tools.keytool
- * @compile -XDignore.symbol.file StartDateTest.java
+ * @modules java.base/sun.security.tools.keytool:+open
  * @run main StartDateTest
  */
 
diff --git a/jdk/test/sun/security/util/DerInputBuffer/DerInputBufferEqualsHashCode.java b/jdk/test/sun/security/util/DerInputBuffer/DerInputBufferEqualsHashCode.java
index 77cea3f..2d04092 100644
--- a/jdk/test/sun/security/util/DerInputBuffer/DerInputBufferEqualsHashCode.java
+++ b/jdk/test/sun/security/util/DerInputBuffer/DerInputBufferEqualsHashCode.java
@@ -26,7 +26,7 @@
  * @author Gary Ellison
  * @bug 4170635
  * @summary Verify equals()/hashCode() contract honored
- * @modules java.base/sun.security.util
+ * @modules java.base/sun.security.util:+open
  *          java.base/sun.security.x509
  * @run main/othervm/policy=Allow.policy DerInputBufferEqualsHashCode
  */
diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData
index a4bae5a..630bea7 100644
--- a/jdk/test/sun/text/resources/LocaleData
+++ b/jdk/test/sun/text/resources/LocaleData
@@ -8293,3 +8293,9 @@
 # bug #8145952
 CurrencyNames//byn=Belarusian Ruble
 CurrencyNames/be_BY/BYN=\u0420\u0443\u0431
+
+# bug #8037111
+FormatData/sv/NumberPatterns/2=#,##0 %
+# bug #8081643
+FormatData/sr-Latin/NumberElements/0=,
+FormatData/sr-Latin/NumberElements/1=.
diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java
index c8631e6..acfcb12 100644
--- a/jdk/test/sun/text/resources/LocaleDataTest.java
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java
@@ -37,7 +37,7 @@
  *      7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
  *      7114053 7074882 7040556 8008577 8013836 8021121 6192407 6931564 8027695
  *      8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361 8134916
- *      8145136 8145952 8164784
+ *      8145136 8145952 8164784 8037111 8081643
  * @summary Verify locale data
  * @modules java.base/sun.util.resources
  * @modules jdk.localedata
diff --git a/jdk/test/sun/tools/jconsole/ResourceCheckTest.java b/jdk/test/sun/tools/jconsole/ResourceCheckTest.java
index 046a7ed..6d91b5b 100644
--- a/jdk/test/sun/tools/jconsole/ResourceCheckTest.java
+++ b/jdk/test/sun/tools/jconsole/ResourceCheckTest.java
@@ -27,6 +27,7 @@
  *  @bug 5008856 5023573 5024917 5062569 7172176
  *  @summary 'missing resource key' error for key = "Operating system"
  *  @modules jdk.jconsole/sun.tools.jconsole
+ *           jdk.jconsole/sun.tools.jconsole.resources:open
  *  @run main ResourceCheckTest
  */
 
diff --git a/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java b/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java
index 0c1d765..14cbfe8 100644
--- a/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java
+++ b/jdk/test/sun/util/calendar/zi/TestZoneInfo310.java
@@ -26,7 +26,7 @@
  * @bug 8007572 8008161 8157792
  * @summary Test whether the TimeZone generated from JSR310 tzdb is the same
  * as the one from the tz data from javazic
- * @modules java.base/sun.util.calendar
+ * @modules java.base/sun.util.calendar:+open
  * @build BackEnd Checksum DayOfWeek Gen GenDoc Main Mappings Month
  *        Rule RuleDay RuleRec Simple TestZoneInfo310 Time Timezone
  *        TzIDOldMapping Zone ZoneInfoFile ZoneInfoOld ZoneRec Zoneinfo
diff --git a/jdk/test/tools/jar/mmrjar/ConcealedPackage.java b/jdk/test/tools/jar/mmrjar/ConcealedPackage.java
index cbe449a..fce5344 100644
--- a/jdk/test/tools/jar/mmrjar/ConcealedPackage.java
+++ b/jdk/test/tools/jar/mmrjar/ConcealedPackage.java
@@ -26,6 +26,8 @@
  * @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
@@ -56,6 +58,7 @@
     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);
@@ -63,7 +66,7 @@
     private final PrintStream err = new PrintStream(errbytes, true);
 
     public ConcealedPackage() throws IOException {
-        Path testsrc = Paths.get(System.getProperty("test.src"));
+        testsrc = Paths.get(System.getProperty("test.src"));
         userdir = Paths.get(System.getProperty("user.dir", "."));
 
         // compile the classes directory
@@ -124,8 +127,7 @@
 
         jar("-tf mmr.jar");
 
-        String s = new String(outbytes.toByteArray());
-        Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+        Set<String> actual = lines(outbytes);
         Set<String> expected = Set.of(
                 "META-INF/",
                 "META-INF/MANIFEST.MF",
@@ -139,10 +141,8 @@
         rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
         Assert.assertEquals(rc, 1);
 
-        s = new String(errbytes.toByteArray());
-        Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
-                + "class not found in base entries")
-        );
+        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
@@ -158,15 +158,11 @@
         Assert.assertEquals(rc, 0);
 
         String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
-                        + "concealed package, \nplacing this jar on the class path "
-                        + "will result in incompatible public interfaces")
-        );
+        Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
 
         jar("-tf mmr.jar");
 
-        s = new String(outbytes.toByteArray());
-        Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+        Set<String> actual = lines(outbytes);
         Set<String> expected = Set.of(
                 "META-INF/",
                 "META-INF/MANIFEST.MF",
@@ -186,9 +182,7 @@
         Assert.assertEquals(rc, 1);
 
         String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
-                + "class not found in base entries")
-        );
+        Assert.assertTrue(Message.NOT_FOUND_IN_BASE_ENTRY.match(s, "p/internal/Bar.class"));
     }
 
     // jar tool succeeds building mmr.jar because of concealed package
@@ -199,15 +193,11 @@
         Assert.assertEquals(rc, 0);
 
         String s = new String(errbytes.toByteArray());
-        Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
-                + "concealed package, \nplacing this jar on the class path "
-                + "will result in incompatible public interfaces")
-        );
+        Assert.assertTrue(Message.NEW_CONCEALED_PACKAGE_WARNING.match(s, "p/internal/Bar.class"));
 
         jar("-tf mmr.jar");
 
-        s = new String(outbytes.toByteArray());
-        Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+        Set<String> actual = lines(outbytes);
         Set<String> expected = Set.of(
                 "META-INF/",
                 "META-INF/MANIFEST.MF",
@@ -222,4 +212,128 @@
         );
         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);
+        }
+    }
 }
diff --git a/jdk/test/tools/jar/mmrjar/src/mr10/p/internal/bar/Gee.java b/jdk/test/tools/jar/mmrjar/src/mr10/p/internal/bar/Gee.java
new file mode 100644
index 0000000..9bb4385
--- /dev/null
+++ b/jdk/test/tools/jar/mmrjar/src/mr10/p/internal/bar/Gee.java
@@ -0,0 +1,7 @@
+package p.internal.bar;
+
+public class Gee {
+    public void geeWhiz() {
+        System.out.println("Gee whiz");
+    }
+}
diff --git a/jdk/test/tools/jar/modularJar/Basic.java b/jdk/test/tools/jar/modularJar/Basic.java
index 073eabc..df38b6c 100644
--- a/jdk/test/tools/jar/modularJar/Basic.java
+++ b/jdk/test/tools/jar/modularJar/Basic.java
@@ -22,19 +22,18 @@
  */
 
 import java.io.*;
+import java.lang.module.ModuleDescriptor;
 import java.lang.reflect.Method;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
+import java.nio.file.*;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.*;
 import java.util.function.Consumer;
 import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import jdk.testlibrary.FileUtils;
@@ -47,6 +46,7 @@
 
 /*
  * @test
+ * @bug 8167328
  * @library /lib/testlibrary
  * @modules jdk.compiler
  *          jdk.jartool
@@ -76,7 +76,8 @@
                                                    Set.of("jdk.test.foo"),
                                                    null, // no uses
                                                    null, // no provides
-                                                   Set.of("jdk.test.foo.internal"));
+                                                   Set.of("jdk.test.foo.internal",
+                                                          "jdk.test.foo.resources"));
     static TestModuleData BAR = new TestModuleData("bar",
                                                    "4.5.6.7",
                                                    "jdk.test.bar.Bar",
@@ -99,17 +100,18 @@
         final String version;
         final String message;
         final String hashes;
-        final Set<String> conceals;
+        final Set<String> packages;
 
         TestModuleData(String mn, String v, String mc, String m, String h,
                        Set<String> requires, Set<String> exports, Set<String> uses,
-                       Set<String> provides, Set<String> conceals) {
+                       Set<String> provides, Set<String> contains) {
             moduleName = mn; mainClass = mc; version = v; message = m; hashes = h;
-            this.requires = requires;
-            this.exports = exports;
-            this.uses = uses;
-            this.provides = provides;
-            this.conceals = conceals;
+            this.requires = requires != null ? requires : Collections.emptySet();
+            this.exports = exports != null ? exports : Collections.emptySet();
+            this.uses = uses != null ? uses : Collections.emptySet();;
+            this.provides = provides != null ? provides : Collections.emptySet();
+            this.packages = Stream.concat(this.exports.stream(), contains.stream())
+                                  .collect(Collectors.toSet());
         }
         static TestModuleData from(String s) {
             try {
@@ -148,8 +150,8 @@
                         provides = stringToSet(line);
                     } else if (line.startsWith("hashes:")) {
                         hashes = line.substring("hashes:".length());
-                    } else if (line.startsWith("conceals:")) {
-                        line = line.substring("conceals:".length());
+                    } else if (line.startsWith("contains:")) {
+                        line = line.substring("contains:".length());
                         conceals = stringToSet(line);
                     } else {
                         throw new AssertionError("Unknown value " + line);
@@ -192,16 +194,14 @@
         assertSetsEqual(expected.exports, received.exports);
         assertSetsEqual(expected.uses, received.uses);
         assertSetsEqual(expected.provides, received.provides);
-        assertSetsEqual(expected.conceals, received.conceals);
+        assertSetsEqual(expected.packages, received.packages);
     }
 
     static void assertSetsEqual(Set<String> s1, Set<String> s2) {
-        if (s1 == null && s2 == null) // none expected, or received
-            return;
-        assertTrue(s1.size() == s2.size(),
-                   "Unexpected set size difference: ", s1.size(), ", ", s2.size());
-        s1.forEach(p -> assertTrue(s2.contains(p), "Expected ", p, ", in ", s2));
-    }
+        if (!s1.equals(s2)) {
+            org.testng.Assert.assertTrue(false, s1 + " vs " + s2);
+        }
+     }
 
     @BeforeTest
     public void compileModules() throws Exception {
@@ -209,6 +209,11 @@
         compileModule(BAR.moduleName, MODULE_CLASSES);
         compileModule("baz");  // for service provider consistency checking
 
+        // copy resources
+        copyResource(TEST_SRC.resolve("src").resolve(FOO.moduleName),
+                     MODULE_CLASSES.resolve(FOO.moduleName),
+                     "jdk/test/foo/resources/foo.properties");
+
         setupMRJARModuleInfo(FOO.moduleName);
         setupMRJARModuleInfo(BAR.moduleName);
         setupMRJARModuleInfo("baz");
@@ -228,6 +233,12 @@
             "--no-manifest",
             "-C", modClasses.toString(), ".")
             .assertSuccess();
+
+        assertSetsEqual(readPackagesAttribute(modularJar),
+                        Set.of("jdk.test.foo",
+                               "jdk.test.foo.resources",
+                               "jdk.test.foo.internal"));
+
         java(mp, FOO.moduleName + "/" + FOO.mainClass)
             .assertSuccess()
             .resultChecker(r -> assertModuleData(r, FOO));
@@ -375,7 +386,8 @@
             "--file=" + modularJar.toString(),
             "--no-manifest",
             "-C", modClasses.toString(), "module-info.class",
-            "-C", modClasses.toString(), "jdk/test/foo/Foo.class")
+            "-C", modClasses.toString(), "jdk/test/foo/Foo.class",
+            "-C", modClasses.toString(), "jdk/test/foo/resources/foo.properties")
             .assertSuccess();
         jar("--update",
             "--file=" + modularJar.toString(),
@@ -471,13 +483,63 @@
                            "Expecting to find \"bar, requires foo,...\"",
                            "in output, but did not: [" + r.output + "]");
                 p = Pattern.compile(
-                        "conceals\\s+jdk.test.foo\\s+conceals\\s+jdk.test.foo.internal");
+                        "contains\\s+jdk.test.foo\\s+contains\\s+jdk.test.foo.internal");
                 assertTrue(p.matcher(r.output).find(),
-                           "Expecting to find \"conceals jdk.test.foo,...\"",
+                           "Expecting to find \"contains jdk.test.foo,...\"",
                            "in output, but did not: [" + r.output + "]");
             });
     }
 
+
+    @Test
+    public void partialUpdateFooPackagesAttribute() throws IOException {
+        Path mp = Paths.get("partialUpdateFooPackagesAttribute");
+        createTestDir(mp);
+        Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+        Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+        // Not all files, and none from non-exported packages,
+        // i.e. no concealed list in first create
+        jar("--create",
+            "--file=" + modularJar.toString(),
+            "--no-manifest",
+            "-C", modClasses.toString(), "module-info.class",
+            "-C", modClasses.toString(), "jdk/test/foo/Foo.class")
+            .assertSuccess();
+
+        assertSetsEqual(readPackagesAttribute(modularJar),
+                        Set.of("jdk.test.foo"));
+
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "-C", modClasses.toString(), "jdk/test/foo/resources/foo.properties")
+            .assertSuccess();
+
+        assertSetsEqual(readPackagesAttribute(modularJar),
+                        Set.of("jdk.test.foo", "jdk.test.foo.resources"));
+
+        jar("--update",
+            "--file=" + modularJar.toString(),
+            "--main-class=" + FOO.mainClass,
+            "--module-version=" + FOO.version,
+            "--no-manifest",
+            "-C", modClasses.toString(), "jdk/test/foo/internal/Message.class")
+            .assertSuccess();
+
+        assertSetsEqual(readPackagesAttribute(modularJar),
+                        Set.of("jdk.test.foo",
+                               "jdk.test.foo.resources",
+                               "jdk.test.foo.internal"));
+
+        java(mp, FOO.moduleName + "/" + FOO.mainClass)
+            .assertSuccess()
+            .resultChecker(r -> assertModuleData(r, FOO));
+    }
+
+    private Set<String> readPackagesAttribute(Path jar) {
+        return getModuleDescriptor(jar).packages();
+    }
+
     @Test
     public void hashBarInFooModule() throws IOException {
         Path mp = Paths.get("dependencesFooBar");
@@ -506,6 +568,7 @@
             .assertSuccess();
 
         java(mp, BAR.moduleName + "/" + BAR.mainClass,
+             "--add-exports", "java.base/jdk.internal.misc=bar",
              "--add-exports", "java.base/jdk.internal.module=bar")
             .assertSuccess()
             .resultChecker(r -> {
@@ -550,6 +613,7 @@
             "-C", barClasses.toString(), ".").assertSuccess();
 
         java(mp, BAR.moduleName + "/" + BAR.mainClass,
+             "--add-exports", "java.base/jdk.internal.misc=bar",
              "--add-exports", "java.base/jdk.internal.module=bar")
             .assertFailure()
             .resultChecker(r -> {
@@ -693,6 +757,14 @@
                                "Expected to find ", FOO.moduleName + "@" + FOO.version,
                                " in [", r.output, "]")
                 );
+
+            jar(option,
+                "--file=" + modularJar.toString(),
+                modularJar.toString())
+            .assertFailure();
+
+            jar(option, modularJar.toString())
+            .assertFailure();
         }
     }
 
@@ -750,12 +822,22 @@
     static Path compileModule(String mn, Path mp)
         throws IOException
     {
-        Path fooSourcePath = TEST_SRC.resolve("src").resolve(mn);
+        Path sourcePath = TEST_SRC.resolve("src").resolve(mn);
         Path build = Files.createDirectories(MODULE_CLASSES.resolve(mn));
-        javac(build, mp, fileList(fooSourcePath));
+        javac(build, mp, sourceList(sourcePath));
         return build;
     }
 
+    static void copyResource(Path srcDir, Path dir, String resource)
+        throws IOException
+    {
+        Path dest = dir.resolve(resource);
+        Files.deleteIfExists(dest);
+
+        Files.createDirectories(dest.getParent());
+        Files.copy(srcDir.resolve(resource), dest);
+    }
+
     static void setupMRJARModuleInfo(String moduleName) throws IOException {
         Path modClasses = MODULE_CLASSES.resolve(moduleName);
         Path metaInfDir = MRJAR_DIR.resolve(moduleName).resolve("META-INF");
@@ -774,6 +856,18 @@
         }
     }
 
+    static ModuleDescriptor getModuleDescriptor(Path jar) {
+        ClassLoader cl = ClassLoader.getSystemClassLoader();
+        try (JarFile jf = new JarFile(jar.toFile())) {
+            JarEntry entry = jf.getJarEntry("module-info.class");
+            try (InputStream in = jf.getInputStream(entry)) {
+                return ModuleDescriptor.read(in);
+            }
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
     // Re-enable when there is support in javax.tools for module path
 //    static void javac(Path dest, Path... sourceFiles) throws IOException {
 //        out.printf("Compiling %d source files %s%n", sourceFiles.length,
@@ -817,6 +911,8 @@
         commands.add(dest.toString());
         if (dest.toString().contains("bar")) {
             commands.add("--add-exports");
+            commands.add("java.base/jdk.internal.misc=bar");
+            commands.add("--add-exports");
             commands.add("java.base/jdk.internal.module=bar");
         }
         if (modulePath != null) {
@@ -848,17 +944,10 @@
         return run(new ProcessBuilder(commands));
     }
 
-    static Path[] fileList(Path directory) throws IOException {
-        final List<Path> filePaths = new ArrayList<>();
-        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult visitFile(Path file,
-                                             BasicFileAttributes attrs) {
-                filePaths.add(file);
-                return FileVisitResult.CONTINUE;
-            }
-        });
-        return filePaths.toArray(new Path[filePaths.size()]);
+    static Path[] sourceList(Path directory) throws IOException {
+        return Files.find(directory, Integer.MAX_VALUE,
+                          (file, attrs) -> (file.toString().endsWith(".java")))
+                    .toArray(Path[]::new);
     }
 
     static void createTestDir(Path p) throws IOException{
diff --git a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java
index 5267814..9232926 100644
--- a/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java
+++ b/jdk/test/tools/jar/modularJar/src/bar/jdk/test/bar/Bar.java
@@ -26,10 +26,14 @@
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
 import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.reflect.Method;
+import java.lang.module.ModuleDescriptor.Provides;
 import java.util.Optional;
 import java.util.StringJoiner;
+import java.util.HashSet;
+import java.util.Set;
 
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.JavaLangModuleAccess;
 import jdk.internal.module.ModuleHashes;
 import jdk.test.bar.internal.Message;
 
@@ -56,19 +60,20 @@
             System.out.println("uses:" + sj.toString());
 
         sj = new StringJoiner(",");
-        md.provides().keySet().stream().sorted().forEach(sj::add);
+        md.provides().stream().map(Provides::service).sorted().forEach(sj::add);
         if (!sj.toString().equals(""))
             System.out.println("provides:" + sj.toString());
 
         sj = new StringJoiner(",");
-        md.conceals().forEach(sj::add);
+        Set<String> concealed = new HashSet<>(md.packages());
+        md.exports().stream().map(Exports::source).forEach(concealed::remove);
+        concealed.forEach(sj::add);
         if (!sj.toString().equals(""))
-            System.out.println("conceals:" + sj.toString());
+            System.out.println("contains:" + sj.toString());
 
-        Method m = ModuleDescriptor.class.getDeclaredMethod("hashes");
-        m.setAccessible(true);
         ModuleDescriptor foo = jdk.test.foo.Foo.class.getModule().getDescriptor();
-        Optional<ModuleHashes> oHashes = (Optional<ModuleHashes>) m.invoke(foo);
+        JavaLangModuleAccess jlma = SharedSecrets.getJavaLangModuleAccess();
+        Optional<ModuleHashes> oHashes = jlma.hashes(foo);
         System.out.println("hashes:" + oHashes.get().hashFor("bar"));
     }
 }
diff --git a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java
index 3e0ce9f..7366bc8 100644
--- a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java
+++ b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/Foo.java
@@ -26,7 +26,10 @@
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
 import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Provides;
 import java.util.StringJoiner;
+import java.util.HashSet;
+import java.util.Set;
 
 import jdk.test.foo.internal.Message;
 
@@ -53,13 +56,15 @@
             System.out.println("uses:" + sj.toString());
 
         sj = new StringJoiner(",");
-        md.provides().keySet().stream().sorted().forEach(sj::add);
+        md.provides().stream().map(Provides::service).sorted().forEach(sj::add);
         if (!sj.toString().equals(""))
             System.out.println("provides:" + sj.toString());
 
         sj = new StringJoiner(",");
-        md.conceals().forEach(sj::add);
+        Set<String> concealed = new HashSet<>(md.packages());
+        md.exports().stream().map(Exports::source).forEach(concealed::remove);
+        concealed.forEach(sj::add);
         if (!sj.toString().equals(""))
-            System.out.println("conceals:" + sj.toString());
+            System.out.println("contains:" + sj.toString());
     }
 }
diff --git a/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/resources/foo.properties b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/resources/foo.properties
new file mode 100644
index 0000000..99b4d5b
--- /dev/null
+++ b/jdk/test/tools/jar/modularJar/src/foo/jdk/test/foo/resources/foo.properties
@@ -0,0 +1 @@
+name = foo
diff --git a/jdk/test/tools/jar/multiRelease/Basic.java b/jdk/test/tools/jar/multiRelease/Basic.java
index 0c7f77e..1d559ad 100644
--- a/jdk/test/tools/jar/multiRelease/Basic.java
+++ b/jdk/test/tools/jar/multiRelease/Basic.java
@@ -25,7 +25,9 @@
  * @test
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
- * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Platform
+ *          jdk.compiler
+ *          jdk.jartool
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils
  * @run testng Basic
  */
 
@@ -39,12 +41,14 @@
 import java.util.*;
 import java.util.function.Consumer;
 import java.util.jar.*;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.zip.*;
 
 import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.Utils;
 
+
 import static java.lang.String.format;
 import static java.lang.System.out;
 
@@ -292,7 +296,7 @@
                 "--release", "9", "-C", classes.resolve("v9").toString(), ".")
                 .assertSuccess()
                 .resultChecker(r ->
-                        assertTrue(r.output.contains("contains a class that is identical"), r.output)
+                        assertTrue(r.outputContains("contains a class that is identical"), r.output)
                 );
 
         delete(jarfile);
@@ -450,7 +454,7 @@
                 "--release", "9", "-C", classes.resolve("v9").toString(), ".")
                 .assertFailure()
                 .resultChecker(r ->
-                        assertTrue(r.output.contains("an isolated nested class"), r.output)
+                        assertTrue(r.outputContains("an isolated nested class"), r.output)
                 );
 
         delete(jarfile);
@@ -605,6 +609,13 @@
             this.ec = ec;
             this.output = output;
         }
+
+        boolean outputContains(String msg) {
+            return Arrays.stream(output.split("\\R"))
+                         .collect(Collectors.joining(" "))
+                         .contains(msg);
+        }
+
         Result assertSuccess() {
             assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
             return this;
diff --git a/jdk/test/tools/jar/multiRelease/Basic1.java b/jdk/test/tools/jar/multiRelease/Basic1.java
new file mode 100644
index 0000000..792b128
--- /dev/null
+++ b/jdk/test/tools/jar/multiRelease/Basic1.java
@@ -0,0 +1,245 @@
+/*
+ * 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
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          jdk.compiler
+ *          jdk.jartool
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.Utils
+ * @run testng Basic1
+ */
+
+import static org.testng.Assert.*;
+
+import org.testng.annotations.*;
+
+import java.io.*;
+import java.nio.file.*;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.jar.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.*;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Utils;
+
+
+import static java.lang.String.format;
+import static java.lang.System.out;
+
+public class Basic1 {
+    private final String src = System.getProperty("test.src", ".");
+
+    @BeforeTest
+    public void setup() throws IOException {
+        String test = "test01";
+        Path classes = Paths.get("classes", "base");
+        Files.createDirectories(classes);
+        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");
+        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");
+        Files.createDirectories(v10);
+        source = Paths.get(src, "data", test, "v10", "version");
+        javac(v10, source.resolve("Version.java"));
+    }
+
+    @Test
+    public void test() throws IOException {
+        String jarfile = "test.jar";
+        Path classes = Paths.get("classes");
+        Path v9 = Paths.get("v9");
+        Path v10 = Paths.get("v10");
+
+        jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+            "--release", "9", "-C", v9.toString(), ".",
+            "--release", "10", "-C", v10.toString(), ".")
+            .assertSuccess();
+
+        checkMultiRelease(jarfile, true);
+
+        Map<String,String[]> names = Map.of(
+            "version/Main.class",
+            new String[] {"classes", "base", "version", "Main.class"},
+
+            "version/Version.class",
+            new String[] {"classes", "base", "version", "Version.class"},
+
+            "META-INF/versions/9/version/Version.class",
+            new String[] {"v9", "META-INF", "versions", "9", "version", "Version.class"},
+
+            "META-INF/versions/10/version/Version.class",
+            new String[] {"v10", "META-INF", "versions", "10", "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");
+
+        jar("cf", jarfile, "-C", classes.resolve("base").toString(), ".",
+            "--release", "9", "-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())) {
+            assertEquals(jf.isMultiRelease(), expected);
+        }
+    }
+
+    // compares the bytes found in the jar entries with the bytes found in the
+    // corresponding data files used to create the entries
+    private void compare(String jarfile, Map<String,String[]> names) throws IOException {
+        try (JarFile jf = new JarFile(jarfile)) {
+            for (String name : names.keySet()) {
+                Path path = Paths.get("", names.get(name));
+                byte[] b1 = Files.readAllBytes(path);
+                byte[] b2;
+                JarEntry je = jf.getJarEntry(name);
+                try (InputStream is = jf.getInputStream(je)) {
+                    b2 = is.readAllBytes();
+                }
+                assertEquals(b1,b2);
+            }
+        }
+    }
+
+    /*
+     * The following methods were taken from modular jar and other jar tests
+     */
+
+    void javac(Path dest, Path... sourceFiles) throws IOException {
+        String javac = JDKToolFinder.getJDKTool("javac");
+
+        List<String> commands = new ArrayList<>();
+        commands.add(javac);
+        String opts = System.getProperty("test.compiler.opts");
+        if (!opts.isEmpty()) {
+            commands.addAll(Arrays.asList(opts.split(" +")));
+        }
+        commands.add("-d");
+        commands.add(dest.toString());
+        Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x));
+
+        quickFail(run(new ProcessBuilder(commands)));
+    }
+
+    Result jarWithStdin(File stdinSource, String... args) {
+        String jar = JDKToolFinder.getJDKTool("jar");
+        List<String> commands = new ArrayList<>();
+        commands.add(jar);
+        commands.addAll(Utils.getForwardVmOptions());
+        Stream.of(args).forEach(x -> commands.add(x));
+        ProcessBuilder p = new ProcessBuilder(commands);
+        if (stdinSource != null)
+            p.redirectInput(stdinSource);
+        return run(p);
+    }
+
+    Result jar(String... args) {
+        return jarWithStdin(null, args);
+    }
+
+    void quickFail(Result r) {
+        if (r.ec != 0)
+            throw new RuntimeException(r.output);
+    }
+
+    Result run(ProcessBuilder pb) {
+        Process p;
+        out.printf("Running: %s%n", pb.command());
+        try {
+            p = pb.start();
+        } catch (IOException e) {
+            throw new RuntimeException(
+                    format("Couldn't start process '%s'", pb.command()), e);
+        }
+
+        String output;
+        try {
+            output = toString(p.getInputStream(), p.getErrorStream());
+        } catch (IOException e) {
+            throw new RuntimeException(
+                    format("Couldn't read process output '%s'", pb.command()), e);
+        }
+
+        try {
+            p.waitFor();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(
+                    format("Process hasn't finished '%s'", pb.command()), e);
+        }
+        return new Result(p.exitValue(), output);
+    }
+
+    String toString(InputStream in1, InputStream in2) throws IOException {
+        try (ByteArrayOutputStream dst = new ByteArrayOutputStream();
+             InputStream concatenated = new SequenceInputStream(in1, in2)) {
+            concatenated.transferTo(dst);
+            return new String(dst.toByteArray(), "UTF-8");
+        }
+    }
+
+    static class Result {
+        final int ec;
+        final String output;
+
+        private Result(int ec, String output) {
+            this.ec = ec;
+            this.output = output;
+        }
+
+        boolean outputContains(String msg) {
+            return Arrays.stream(output.split("\\R"))
+                         .collect(Collectors.joining(" "))
+                         .contains(msg);
+        }
+
+        Result assertSuccess() {
+            assertTrue(ec == 0, format("ec: %d, output: %s", ec, output));
+            return this;
+        }
+        Result assertFailure() {
+            assertTrue(ec != 0, format("ec: %d, output: %s", ec, output));
+            return this;
+        }
+        Result resultChecker(Consumer<Result> r) { r.accept(this); return this; }
+    }
+}
diff --git a/jdk/test/tools/jlink/IntegrationTest.java b/jdk/test/tools/jlink/IntegrationTest.java
index 17dcfde..8d6bb30 100644
--- a/jdk/test/tools/jlink/IntegrationTest.java
+++ b/jdk/test/tools/jlink/IntegrationTest.java
@@ -59,7 +59,6 @@
  * @library ../lib
  * @modules java.base/jdk.internal.jimage
  *          jdk.jdeps/com.sun.tools.classfile
- *          jdk.jlink/jdk.tools.jlink
  *          jdk.jlink/jdk.tools.jlink.builder
  *          jdk.jlink/jdk.tools.jlink.internal
  *          jdk.jlink/jdk.tools.jlink.internal.plugins
diff --git a/jdk/test/tools/jlink/JLinkNegativeTest.java b/jdk/test/tools/jlink/JLinkNegativeTest.java
index 95ed27b..f8ac809 100644
--- a/jdk/test/tools/jlink/JLinkNegativeTest.java
+++ b/jdk/test/tools/jlink/JLinkNegativeTest.java
@@ -274,7 +274,7 @@
                 helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName2, classNames);
 
         try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) {
-            ModuleInfoWriter.write(new ModuleDescriptor.Builder(moduleName1)
+            ModuleInfoWriter.write(ModuleDescriptor.module(moduleName1)
                     .requires("java.base").build(), out);
         }
 
@@ -332,7 +332,7 @@
                 helper.getJarSrcDir(), helper.getJarClassesDir(), moduleName2, classNames);
 
         try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) {
-            ModuleInfoWriter.write(new ModuleDescriptor.Builder(moduleName1)
+            ModuleInfoWriter.write(ModuleDescriptor.module(moduleName1)
                     .requires("java.base").build(), out);
         }
 
diff --git a/jdk/test/tools/jlink/JLinkTest.java b/jdk/test/tools/jlink/JLinkTest.java
index 79a920b..4d12ddc 100644
--- a/jdk/test/tools/jlink/JLinkTest.java
+++ b/jdk/test/tools/jlink/JLinkTest.java
@@ -62,9 +62,11 @@
     // number of built-in plugins from jdk.jlink module
     private static int getNumJlinkPlugins() {
         ModuleDescriptor desc = Plugin.class.getModule().getDescriptor();
-        return desc.provides().
-                    get(Plugin.class.getName()).
-                    providers().size();
+        return desc.provides().stream()
+                .filter(p -> p.service().equals(Plugin.class.getName()))
+                .map(p -> p.providers().size())
+                .findAny()
+                .orElse(0);
     }
 
     private static boolean isOfJLinkModule(Plugin p) {
diff --git a/jdk/test/tools/jlink/basic/AllModulePath.java b/jdk/test/tools/jlink/basic/AllModulePath.java
new file mode 100644
index 0000000..3053c34
--- /dev/null
+++ b/jdk/test/tools/jlink/basic/AllModulePath.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary jlink test of --add-module ALL-MODULE-PATH
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build jdk.testlibrary.ProcessTools
+ *        jdk.testlibrary.OutputAnalyzer
+ *        CompilerUtils
+ * @run testng AllModulePath
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.spi.ToolProvider;
+
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class AllModulePath {
+
+    private final Path JMODS = Paths.get(System.getProperty("test.jdk")).resolve("jmods");
+    private final Path SRC = Paths.get(System.getProperty("test.src")).resolve("src");
+    private final Path MODS = Paths.get("mods");
+
+    private final static Set<String> MODULES = Set.of("test", "m1");
+
+    static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
+        .orElseThrow(() ->
+            new RuntimeException("jlink tool not found")
+        );
+
+    @BeforeClass
+    public void setup() throws Throwable {
+        if (Files.notExists(JMODS)) {
+            return;
+        }
+
+        Files.createDirectories(MODS);
+
+        for (String mn : MODULES) {
+            Path mod = MODS.resolve(mn);
+            if (!CompilerUtils.compile(SRC.resolve(mn), mod)) {
+                throw new AssertionError("Compilation failure. See log.");
+            }
+        }
+    }
+
+    @Test
+    public void testAllModulePath() throws Throwable {
+        if (Files.notExists(JMODS)) {
+            return;
+        }
+
+        // create custom image
+        Path image = Paths.get("image");
+        createImage(image, "--add-modules", "ALL-MODULE-PATH");
+
+        Set<String> modules = new HashSet<>();
+        Files.find(JMODS, 1, (Path p, BasicFileAttributes attr) ->
+                                p.toString().endsWith(".jmod"))
+             .map(p -> JMODS.relativize(p).toString())
+             .map(n -> n.substring(0, n.length()-5))
+             .forEach(modules::add);
+        modules.add("m1");
+        modules.add("test");
+        checkModules(image, modules);
+    }
+
+    @Test
+    public void testLimitModules() throws Throwable {
+        if (Files.notExists(JMODS)) {
+            return;
+        }
+
+        // create custom image
+        Path image = Paths.get("image1");
+        createImage(image,
+                    "--add-modules", "ALL-MODULE-PATH",
+                    "--limit-modules", "m1");
+
+        checkModules(image, Set.of("m1", "java.base"));
+    }
+
+    @Test
+    public void testAddModules() throws Throwable {
+        if (Files.notExists(JMODS)) {
+            return;
+        }
+
+        // create custom image
+        Path image = Paths.get("image2");
+        createImage(image,
+                    "--add-modules", "m1,test",
+                    "--add-modules", "ALL-MODULE-PATH",
+                    "--limit-modules", "java.base");
+
+        checkModules(image, Set.of("m1", "test", "java.base"));
+    }
+
+    /*
+     * check the modules linked in the image
+     */
+    private void checkModules(Path image, Set<String> modules) throws Throwable {
+        Path cmd = findTool(image, "java");
+
+        List<String> options = new ArrayList<>();
+        options.add(cmd.toString());
+        options.add("-m");
+        options.add("m1/p.ListModules");
+        options.addAll(modules);
+
+        ProcessBuilder pb = new ProcessBuilder(options);
+        ProcessTools.executeCommand(pb)
+                    .shouldHaveExitValue(0);
+    }
+
+    private Path findTool(Path image, String tool)  {
+        String suffix = System.getProperty("os.name").startsWith("Windows")
+                            ? ".exe" : "";
+
+        Path cmd = image.resolve("bin").resolve(tool + suffix);
+        if (Files.notExists(cmd)) {
+            throw new RuntimeException(cmd + " not found");
+        }
+        return cmd;
+    }
+
+    private void createImage(Path image, String... options) throws IOException {
+        String modulepath = JMODS.toString() + File.pathSeparator + MODS.toString();
+        List<String> opts = List.of("--module-path", modulepath,
+                                    "--output", image.toString());
+        String[] args = Stream.concat(opts.stream(), Arrays.stream(options))
+                              .toArray(String[]::new);
+
+        System.out.println("jlink " + Arrays.stream(args).collect(Collectors.joining(" ")));
+        PrintWriter pw = new PrintWriter(System.out);
+        int rc = JLINK_TOOL.run(pw, pw, args);
+        assertTrue(rc == 0);
+    }
+}
diff --git a/jdk/test/tools/jlink/basic/BasicTest.java b/jdk/test/tools/jlink/basic/BasicTest.java
index 6ddc4a1..87b2b0e 100644
--- a/jdk/test/tools/jlink/basic/BasicTest.java
+++ b/jdk/test/tools/jlink/basic/BasicTest.java
@@ -59,10 +59,11 @@
             new RuntimeException("jlink tool not found")
         );
 
+    private final String TEST_MODULE = "test";
     private final Path jdkHome = Paths.get(System.getProperty("test.jdk"));
     private final Path jdkMods = jdkHome.resolve("jmods");
     private final Path testSrc = Paths.get(System.getProperty("test.src"));
-    private final Path src = testSrc.resolve("src");
+    private final Path src = testSrc.resolve("src").resolve(TEST_MODULE);
     private final Path classes = Paths.get("classes");
     private final Path jmods = Paths.get("jmods");
     private final Path jars = Paths.get("jars");
@@ -80,23 +81,22 @@
             throw new AssertionError("Compilation failure. See log.");
         }
 
-        String modName = "test";
         Files.createDirectories(jmods);
         Files.createDirectories(jars);
         Path jarfile = jars.resolve("test.jar");
         JarUtils.createJarFile(jarfile, classes);
 
         Path image = Paths.get("mysmallimage");
-        runJmod(jarfile.toString(), modName);
-        runJlink(image, modName, "--compress", "2");
-        execute(image, modName);
+        runJmod(jarfile.toString(), TEST_MODULE);
+        runJlink(image, TEST_MODULE, "--compress", "2");
+        execute(image, TEST_MODULE);
 
-        Files.delete(jmods.resolve(modName + ".jmod"));
+        Files.delete(jmods.resolve(TEST_MODULE + ".jmod"));
 
         image = Paths.get("myimage");
-        runJmod(classes.toString(), modName);
-        runJlink(image, modName);
-        execute(image, modName);
+        runJmod(classes.toString(), TEST_MODULE);
+        runJlink(image, TEST_MODULE);
+        execute(image, TEST_MODULE);
     }
 
     private void execute(Path image, String moduleName) throws Throwable {
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/tools/jlink/basic/src/m1/module-info.java
similarity index 95%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/tools/jlink/basic/src/m1/module-info.java
index 9d2c8be..f6ecf6b 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/tools/jlink/basic/src/m1/module-info.java
@@ -22,6 +22,4 @@
  */
 
 module m1 {
-    requires unsupported;
-    exports p1;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/jdk/test/tools/jlink/basic/src/m1/p/ListModules.java
similarity index 61%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to jdk/test/tools/jlink/basic/src/m1/p/ListModules.java
index 789cdb9..611946c 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/jdk/test/tools/jlink/basic/src/m1/p/ListModules.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -21,13 +21,28 @@
  * questions.
  */
 
-package p7;
+package p;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class ListModules {
     public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+        Set<String> modules = ModuleFinder.ofSystem().findAll()
+            .stream()
+            .map(ModuleReference::descriptor)
+            .map(ModuleDescriptor::name)
+            .collect(Collectors.toSet());
+
+        Set<String> expected = Arrays.stream(args).collect(Collectors.toSet());
+
+        if (!modules.equals(expected)) {
+            throw new RuntimeException(modules + " != " + expected);
+        }
+
     }
 }
diff --git a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
index 712f987..9137ed3 100644
--- a/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
+++ b/jdk/test/tools/jlink/plugins/FileCopierPluginTest.java
@@ -75,11 +75,11 @@
 
         String target = "target" + File.separator + name;
         Files.write(txt.toPath(), content.getBytes());
-        File lic = new File(System.getProperty("java.home"), "LICENSE");
+        File lic = new File(System.getProperty("java.home"), "LICENSE.txt");
         StringBuilder builder = new StringBuilder();
         int expected = lic.exists() ? 4 : 3;
         if (lic.exists()) {
-            builder.append("LICENSE,");
+            builder.append("LICENSE.txt,");
         }
         builder.append(txt.getAbsolutePath()+",");
         builder.append(txt.getAbsolutePath() + "=" + target+",");
@@ -116,9 +116,9 @@
         imgbuilder.storeFiles(pool);
 
         if (lic.exists()) {
-            File license = new File(root.toFile(), "LICENSE");
+            File license = new File(root.toFile(), "LICENSE.txt");
             if (!license.exists() || license.length() == 0) {
-                throw new AssertionError("Invalide license file "
+                throw new AssertionError("Invalid license file "
                         + license.getAbsoluteFile());
             }
         }
diff --git a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java
index 7b4a1bc..d74b6b8 100644
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java
@@ -22,11 +22,10 @@
  */
 
 import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
+import java.lang.module.ModuleDescriptor.*;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReference;
-import java.util.Collections;
-import java.util.EnumSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -58,14 +57,32 @@
     }
 
     private void testModuleDescriptor(ModuleDescriptor md) {
-        assertUnmodifiable(md.conceals(), "conceal");
         assertUnmodifiable(md.packages(), "package");
         assertUnmodifiable(md.requires(),
-                           jlma.newRequires(EnumSet.allOf(Modifier.class), "require"));
-        assertUnmodifiable(md.exports(), jlma.newExports("export"));
+                           jlma.newRequires(Set.of(Requires.Modifier.TRANSITIVE), "require"));
+        for (Requires req : md.requires()) {
+            assertUnmodifiable(req.modifiers(), Requires.Modifier.TRANSITIVE);
+        }
+
+        assertUnmodifiable(md.exports(), jlma.newExports(Set.of(), "export", Set.of()));
+        for (Exports exp : md.exports()) {
+            assertUnmodifiable(exp.modifiers(), Exports.Modifier.SYNTHETIC);
+            assertUnmodifiable(exp.targets(), "target");
+        }
+
+        assertUnmodifiable(md.opens(), jlma.newOpens(Set.of(), "open", Set.of()));
+        for (Opens opens : md.opens()) {
+            assertUnmodifiable(opens.modifiers(), Opens.Modifier.SYNTHETIC);
+            assertUnmodifiable(opens.targets(), "target");
+        }
+
         assertUnmodifiable(md.uses(), "use");
-        assertUnmodifiable(md.provides(), "provide",
-                           jlma.newProvides("provide", Collections.singleton("provide")));
+
+        assertUnmodifiable(md.provides(),
+                           jlma.newProvides("provide", List.of("provide")));
+        for (Provides provides : md.provides()) {
+            assertUnmodifiable(provides.providers(), "provide");
+        }
 
     }
 
@@ -80,6 +97,17 @@
         }
     }
 
+    private <T> void assertUnmodifiable(List<T> list, T dummy) {
+        try {
+            list.add(dummy);
+            fail("Should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            // pass
+        } catch (Exception e) {
+            fail("Should throw UnsupportedOperationException");
+        }
+    }
+
     private <T, V> void assertUnmodifiable(Map<T, V> set, T dummyKey, V dummyValue) {
         try {
             set.put(dummyKey, dummyValue);
diff --git a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java
index a56da48..0875db2 100644
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java
@@ -52,9 +52,11 @@
     private static final Path MODS_DIR = Paths.get("mods");
     private static final Path IMAGE = Paths.get("image");
     private static final Path JMODS = Paths.get(JAVA_HOME, "jmods");
+    private static final String MAIN_MID = "m1/p1.Main";
 
     // the names of the modules in this test
-    private static String[] modules = new String[] {"m1", "m2", "m3"};
+    private static String[] modules = new String[] {"m1", "m2", "m3", "m4"};
+
 
     private static boolean hasJmods() {
         if (!Files.exists(JMODS)) {
@@ -80,7 +82,7 @@
             FileUtils.deleteFileTreeUnchecked(IMAGE);
         }
 
-        createImage(IMAGE, "java.base", "m1");
+        createImage(IMAGE, "java.base", "m1", "m3");
     }
 
     private void createImage(Path outputDir, String... modules) throws Throwable {
@@ -96,20 +98,34 @@
 
     /*
      * Test the image created when linking with a module with
-     * no ConcealedPackages attribute
+     * no Packages attribute
      */
     @Test
-    public void test() throws Throwable {
+    public void testPackagesAttribute() throws Throwable {
         if (!hasJmods()) return;
 
         Path java = IMAGE.resolve("bin").resolve("java");
-        assertTrue(executeProcess(java.toString(), "-m", "m1/p1.Main")
+        assertTrue(executeProcess(java.toString(), "-m", MAIN_MID)
                         .outputTo(System.out)
                         .errorTo(System.out)
                         .getExitValue() == 0);
     }
 
     /*
+     * Test the image created when linking with an open module
+    */
+    @Test
+    public void testOpenModule() throws Throwable {
+        if (!hasJmods()) return;
+
+        Path java = IMAGE.resolve("bin").resolve("java");
+        assertTrue(executeProcess(java.toString(), "-m", "m3/p3.Main")
+            .outputTo(System.out)
+            .errorTo(System.out)
+            .getExitValue() == 0);
+    }
+
+    /*
      * Disable the fast loading of system modules.
      * Parsing module-info.class
      */
@@ -120,7 +136,7 @@
         Path java = IMAGE.resolve("bin").resolve("java");
         assertTrue(executeProcess(java.toString(),
                                   "-Djdk.system.module.finder.disabledFastPath",
-                                  "-m", "m1/p1.Main")
+                                  "-m", MAIN_MID)
                         .outputTo(System.out)
                         .errorTo(System.out)
                         .getExitValue() == 0);
@@ -135,9 +151,9 @@
         if (!hasJmods()) return;
 
         Path dir = Paths.get("newImage");
-        createImage(dir, "java.base", "m1", "m2", "m3");
+        createImage(dir, "java.base", "m1", "m2", "m3", "m4");
         Path java = dir.resolve("bin").resolve("java");
-        assertTrue(executeProcess(java.toString(), "-m", "m1/p1.Main")
+        assertTrue(executeProcess(java.toString(), "-m", MAIN_MID)
                         .outputTo(System.out)
                         .errorTo(System.out)
                         .getExitValue() == 0);
diff --git a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java
index 40bb1ca..d19856a 100644
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java
@@ -48,7 +48,6 @@
     }
 
     static void validate(ModuleDescriptor md) {
-        checkPackages(md.conceals(), "p1", "p2");
         checkPackages(md.packages(), "p1", "p2");
     }
 
diff --git a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/module-info.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/module-info.java
index b164b24..c2e7fb6 100644
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/module-info.java
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/module-info.java
@@ -22,4 +22,5 @@
  */
 
 module m3 {
+    requires m4;
 }
diff --git a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/p3/Main.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/p3/Main.java
new file mode 100644
index 0000000..c7ff38e
--- /dev/null
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m3/p3/Main.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p3;
+
+import p4.Foo;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Module;
+
+import static java.lang.module.ModuleDescriptor.Exports.Modifier.*;
+
+/**
+ * Test if m4 is an open module and p4 is package that m3 can access
+ */
+public class Main {
+    public static void main(String... args) throws Exception {
+        Module m4 = Foo.class.getModule();
+        if (!m4.isOpen("p4")) {
+            throw new RuntimeException("m3 can't access p4");
+        }
+
+        // Test if it can access a private field
+        Foo foo = Foo.create("foo");
+
+        Field field = Foo.class.getDeclaredField("name");
+        field.setAccessible(true);
+        String name = (String) field.get(foo);
+        if (!name.equals("foo")) {
+            throw new RuntimeException("unexpected Foo::name value = " + name);
+        }
+
+        checkOpenModule();
+    }
+
+    // check the module descriptor of the open module m4
+    static void checkOpenModule() {
+        ModuleDescriptor md = Foo.class.getModule().getDescriptor();
+        System.out.println(md);
+
+        if (!md.isOpen()) {
+            throw new RuntimeException("m4 is a open module");
+        }
+
+        if (md.packages().size() != 1 || !md.packages().contains("p4")) {
+            throw new RuntimeException("unexpected m4 packages: " + md.packages());
+        }
+
+        if (!md.opens().isEmpty()) {
+            throw new RuntimeException("unexpected m4 opens: " + md.opens());
+        }
+    }
+
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/module-info.java
index 9d2c8be..c57da1b 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/module-info.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+open module m4 {
+    exports p4;
 }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Foo.java
similarity index 82%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Foo.java
index 242f168..84447c5 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Foo.java
@@ -21,5 +21,16 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package p4;
+
+public class Foo {
+    private final String name;
+
+    private Foo(String name) {
+        this.name = name;
+    }
+
+    public static Foo create(String name) {
+        return new Foo(name);
+    }
+}
diff --git a/jdk/test/tools/jmod/JmodTest.java b/jdk/test/tools/jmod/JmodTest.java
index f3224c2..46a9217 100644
--- a/jdk/test/tools/jmod/JmodTest.java
+++ b/jdk/test/tools/jmod/JmodTest.java
@@ -23,13 +23,13 @@
 
 /*
  * @test
+ * @bug 8142968
+ * @summary Basic test for jmod
  * @library /lib/testlibrary
  * @modules jdk.compiler
  *          jdk.jlink
  * @build jdk.testlibrary.FileUtils CompilerUtils
  * @run testng JmodTest
- * @bug 8142968
- * @summary Basic test for jmod
  */
 
 import java.io.*;
@@ -76,6 +76,9 @@
         for (String name : new String[] { "foo"/*, "bar", "baz"*/ } ) {
             Path dir = EXPLODED_DIR.resolve(name);
             assertTrue(compileModule(name, dir.resolve("classes")));
+            copyResource(SRC_DIR.resolve("foo"),
+                         dir.resolve("classes"),
+                         "jdk/test/foo/resources/foo.properties");
             createCmds(dir.resolve("bin"));
             createLibs(dir.resolve("lib"));
             createConfigs(dir.resolve("conf"));
@@ -127,6 +130,7 @@
                 assertContains(r.output, CLASSES_PREFIX + "module-info.class");
                 assertContains(r.output, CLASSES_PREFIX + "jdk/test/foo/Foo.class");
                 assertContains(r.output, CLASSES_PREFIX + "jdk/test/foo/internal/Message.class");
+                assertContains(r.output, CLASSES_PREFIX + "jdk/test/foo/resources/foo.properties");
             });
     }
 
@@ -279,6 +283,7 @@
                  Set<String> expectedFilenames = new HashSet<>();
                  expectedFilenames.add(CLASSES_PREFIX + "module-info.class");
                  expectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/Foo.class");
+                 expectedFilenames.add(CLASSES_PREFIX + "jdk/test/foo/resources/foo.properties");
                  expectedFilenames.add(LIBS_PREFIX + "second.so");
                  expectedFilenames.add(LIBS_PREFIX + "third/third.so");
                  assertJmodContent(jmod, expectedFilenames);
@@ -303,15 +308,15 @@
              .assertSuccess()
              .resultChecker(r -> {
                  // Expect similar output: "foo,  requires mandated java.base
-                 // exports jdk.test.foo,  conceals jdk.test.foo.internal"
+                 // exports jdk.test.foo,  contains jdk.test.foo.internal"
                  Pattern p = Pattern.compile("\\s+foo\\s+requires\\s+mandated\\s+java.base");
                  assertTrue(p.matcher(r.output).find(),
                            "Expecting to find \"foo, requires java.base\"" +
                                 "in output, but did not: [" + r.output + "]");
                  p = Pattern.compile(
-                        "exports\\s+jdk.test.foo\\s+conceals\\s+jdk.test.foo.internal");
+                        "exports\\s+jdk.test.foo\\s+contains\\s+jdk.test.foo.internal");
                  assertTrue(p.matcher(r.output).find(),
-                           "Expecting to find \"exports ..., conceals ...\"" +
+                           "Expecting to find \"exports ..., contains ...\"" +
                                 "in output, but did not: [" + r.output + "]");
              });
     }
@@ -369,6 +374,26 @@
     }
 
     @Test
+    public void testPackagesAttribute() throws IOException {
+        Path jmod = MODS_DIR.resolve("foo.jmod");
+        FileUtils.deleteFileIfExistsWithRetry(jmod);
+        String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
+
+        Set<String> expectedPackages = Set.of("jdk.test.foo",
+                                              "jdk.test.foo.internal",
+                                              "jdk.test.foo.resources");
+
+        jmod("create",
+             "--class-path", cp,
+             jmod.toString())
+             .assertSuccess()
+             .resultChecker(r -> {
+                 Set<String> pkgs = getModuleDescriptor(jmod).packages();
+                 assertEquals(pkgs, expectedPackages);
+             });
+        }
+
+    @Test
     public void testVersion() {
         jmod("--version")
             .assertSuccess()
@@ -557,6 +582,14 @@
         }
     }
 
+    static void copyResource(Path srcDir, Path dir, String resource) throws IOException {
+        Path dest = dir.resolve(resource);
+        Files.deleteIfExists(dest);
+
+        Files.createDirectories(dest.getParent());
+        Files.copy(srcDir.resolve(resource), dest);
+    }
+
     // Standalone entry point.
     public static void main(String[] args) throws Throwable {
         JmodTest test = new JmodTest();
diff --git a/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java b/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java
index a269fd5..8a13007 100644
--- a/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java
+++ b/jdk/test/tools/jmod/hashes/src/org.bar/module-info.java
@@ -22,5 +22,5 @@
  */
 
 module org.bar {
-    requires public m1;
+    requires transitive m1;
 }
diff --git a/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java b/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java
index b143d5b..0563990 100644
--- a/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java
+++ b/jdk/test/tools/jmod/hashes/src/org.foo/module-info.java
@@ -22,5 +22,5 @@
  */
 
 module org.foo {
-    requires public org.bar;
+    requires transitive org.bar;
 }
diff --git a/jdk/test/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties b/jdk/test/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties
new file mode 100644
index 0000000..8f6224d
--- /dev/null
+++ b/jdk/test/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties
@@ -0,0 +1 @@
+name = foo 
diff --git a/jdk/test/tools/launcher/InfoStreams.java b/jdk/test/tools/launcher/InfoStreams.java
new file mode 100644
index 0000000..dc0e2da
--- /dev/null
+++ b/jdk/test/tools/launcher/InfoStreams.java
@@ -0,0 +1,78 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @build InfoStreams jdk.testlibrary.ProcessTools
+ * @run main InfoStreams
+ * @summary Test that informational options use the correct streams
+ */
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+
+
+public class InfoStreams {
+
+    public static OutputAnalyzer run(String ... opts) throws Exception {
+        return ProcessTools.executeTestJava(opts).shouldHaveExitValue(0);
+    }
+
+    private static final String
+        java_version = System.getProperty("java.version"),
+        USAGE = "^Usage: java ",
+        VERSION_ERR = "^(java|openjdk) version \"" + java_version + "\"",
+        VERSION_OUT = "^(java|openjdk) " + java_version,
+        FULLVERSION_ERR = "^(java|openjdk) full version \"" + java_version + ".*\"",
+        FULLVERSION_OUT = "^(java|openjdk) " + java_version,
+        NONSTD = ".*These extra options are subject to change";
+
+    public static void main(String ... args) throws Exception {
+
+        String classPath = System.getProperty("java.class.path");
+
+        run("-help").stderrShouldMatch(USAGE).stdoutShouldNotMatch(".");
+        run("--help").stdoutShouldMatch(USAGE).stderrShouldNotMatch(".");
+
+        run("-version").stderrShouldMatch(VERSION_ERR).stdoutShouldNotMatch(".");
+        run("--version").stdoutShouldMatch(VERSION_OUT).stderrShouldNotMatch(".");
+
+        run("-showversion", "--dry-run", "-cp", classPath, "InfoStreams")
+            .stderrShouldMatch(VERSION_ERR)
+            .stdoutShouldNotMatch(".");
+        run("--show-version", "--dry-run", "-cp", classPath, "InfoStreams")
+            .stdoutShouldMatch(VERSION_OUT)
+            .stderrShouldNotMatch(".");
+
+        run("-fullversion").stderrShouldMatch(FULLVERSION_ERR)
+            .stdoutShouldNotMatch(".");
+        run("--full-version").stdoutShouldMatch(FULLVERSION_OUT)
+            .stderrShouldNotMatch(".");
+
+        run("-X").stderrShouldMatch(NONSTD).stdoutShouldNotMatch(".");
+        run("--help-extra").stdoutShouldMatch(NONSTD).stderrShouldNotMatch(".");
+
+    }
+
+}
diff --git a/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java b/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java
index cc9b174..c92824f 100644
--- a/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java
+++ b/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java
@@ -32,7 +32,9 @@
 
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.stream.Stream;
 
+import jdk.testlibrary.OutputAnalyzer;
 import static jdk.testlibrary.ProcessTools.*;
 
 import org.testng.annotations.BeforeTest;
@@ -202,13 +204,15 @@
 
 
     /**
-     * --add-exports allows duplicates
+     * --add-exports and --add-opens allows duplicates
      */
     public void testWithDuplicateOption() throws Exception {
 
         int exitValue
             =  executeTestJava("--add-exports", "java.base/jdk.internal.reflect=ALL-UNNAMED",
                                "--add-exports", "java.base/jdk.internal.reflect=ALL-UNNAMED",
+                               "--add-opens", "java.base/java.util=ALL-UNNAMED",
+                               "--add-opens", "java.base/java.util=ALL-UNNAMED",
                                "-version")
                 .outputTo(System.out)
                 .errorTo(System.out)
@@ -218,24 +222,34 @@
     }
 
 
+    private OutputAnalyzer execJava(String... options) {
+        try {
+            return executeTestJava(options);
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+
     /**
-     * Exercise --add-exports with unknown values.  Warning is emitted.
+     * Exercise --add-exports and --add-opens with unknown values.
+     * Warning is emitted.
      */
     @Test(dataProvider = "unknownvalues")
-    public void testWithUnknownValue(String value, String ignore) throws Exception {
+    public void testWithUnknownValue(String value, String ignore) {
+        Stream.of("--add-exports", "--add-opens")
+            .forEach(option -> {
+                //  --add-exports $VALUE -version
+                int exitValue = execJava(option, value, "-version")
+                    .stderrShouldMatch("WARNING: .*.monkey.*")
+                    .outputTo(System.out)
+                    .errorTo(System.out)
+                    .getExitValue();
 
-        //  --add-exports $VALUE -version
-        int exitValue =
-            executeTestJava("--add-exports", value,
-                            "-version")
-                .stderrShouldMatch("WARNING: .*.monkey.*")
-                .outputTo(System.out)
-                .errorTo(System.out)
-                .getExitValue();
-
-        assertTrue(exitValue == 0);
+                assertTrue(exitValue == 0);
+            });
     }
 
+
     @DataProvider(name = "unknownvalues")
     public Object[][] unknownValues() {
         return new Object[][]{
@@ -250,20 +264,20 @@
 
 
     /**
-     * Exercise --add-exports with bad values
+     * Exercise --add-exports and --add-opens with bad values
      */
     @Test(dataProvider = "badvalues")
-    public void testWithBadValue(String value, String ignore) throws Exception {
-
-        //  --add-exports $VALUE -version
-        int exitValue =
-            executeTestJava("--add-exports", value,
-                            "-version")
-                .outputTo(System.out)
-                .errorTo(System.out)
-                .getExitValue();
+    public void testWithBadValue(String value, String ignore) {
+        Stream.of("--add-exports", "--add-opens")
+            .forEach(option -> {
+                //  --add-exports $VALUE -version
+                int exitValue = execJava(option, value, "-version")
+                    .outputTo(System.out)
+                    .errorTo(System.out)
+                    .getExitValue();
 
         assertTrue(exitValue != 0);
+            });
     }
 
     @DataProvider(name = "badvalues")
diff --git a/jdk/test/tools/launcher/modules/addexports/manifest/AddExportsAndOpensInManifest.java b/jdk/test/tools/launcher/modules/addexports/manifest/AddExportsAndOpensInManifest.java
new file mode 100644
index 0000000..c9abb2c
--- /dev/null
+++ b/jdk/test/tools/launcher/modules/addexports/manifest/AddExportsAndOpensInManifest.java
@@ -0,0 +1,175 @@
+/*
+ * 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
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build AddExportsAndOpensInManifest Test2 JarUtils jdk.testlibrary.*
+ * @compile --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED Test1.java
+ * @run testng AddExportsAndOpensInManifest
+ * @summary Basic test for Add-Exports and Add-Opens attributes in the
+ *          manifest of a main application JAR
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import jdk.testlibrary.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class AddExportsAndOpensInManifest {
+
+    /**
+     * Package Test1 and Test2 into a JAR file with the given attributes
+     * in the JAR manifest, then execute the JAR file with `java -jar`.
+     */
+    private OutputAnalyzer runTest(String attributes) throws Exception {
+        Manifest man = new Manifest();
+        Attributes attrs = man.getMainAttributes();
+        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+
+        for (String nameAndValue : attributes.split(",")) {
+            String[] s = nameAndValue.split("=");
+            if (s.length != 2)
+                throw new RuntimeException("Malformed: " + nameAndValue);
+            String name = s[0];
+            String value = s[1];
+            attrs.put(new Attributes.Name(name), value);
+        }
+
+        // create the JAR file with Test1 and Test2
+        Path jarfile = Paths.get("test.jar");
+        Files.deleteIfExists(jarfile);
+
+        Path classes = Paths.get(System.getProperty("test.classes", ""));
+        JarUtils.createJarFile(jarfile, man, classes,
+                Paths.get("Test1.class"), Paths.get("Test2.class"));
+
+        // java -jar test.jar
+        return ProcessTools.executeTestJava("-jar", jarfile.toString())
+                .outputTo(System.out)
+                .errorTo(System.out);
+    }
+
+    /**
+     * Run test with the given JAR attributes, expecting the test to pass
+     */
+    private void runExpectingPass(String attrs) throws Exception {
+        int exitValue = runTest(attrs).getExitValue();
+        assertTrue(exitValue == 0);
+    }
+
+    /**
+     * Run test with the given JAR attributes, expecting the test to fail
+     * with at least the given output
+     */
+    private void runExpectingFail(String attrs, String errorString) throws Exception {
+        int exitValue = runTest(attrs).shouldContain(errorString).getExitValue();
+        assertTrue(exitValue != 0);
+    }
+
+
+    /**
+     * Run tests to make sure that they fail in the expected way.
+     */
+    public void testSanity() throws Exception {
+        runExpectingFail("Main-Class=Test1", "IllegalAccessError");
+        runExpectingFail("Main-Class=Test2", "InaccessibleObjectException");
+    }
+
+    /**
+     * Run tests with the Add-Exports attribute in the main manifest.
+     */
+    public void testWithAddExports() throws Exception {
+        runExpectingPass("Main-Class=Test1,Add-Exports=java.base/jdk.internal.misc");
+        runExpectingFail("Main-Class=Test2,Add-Exports=java.base/jdk.internal.misc",
+                         "InaccessibleObjectException");
+
+        // run with leading and trailing spaces
+        runExpectingPass("Main-Class=Test1,Add-Exports=  java.base/jdk.internal.misc");
+        runExpectingPass("Main-Class=Test1,Add-Exports=java.base/jdk.internal.misc  ");
+
+        // run with multiple values
+        runExpectingPass("Main-Class=Test1,Add-Exports=java.base/jdk.internal.misc"
+                + " java.base/jdk.internal.loader");
+        runExpectingPass("Main-Class=Test1,Add-Exports=java.base/jdk.internal.loader"
+                + " java.base/jdk.internal.misc");
+
+        // run with duplicate values
+        runExpectingPass("Main-Class=Test1,Add-Exports=java.base/jdk.internal.misc"
+                + " java.base/jdk.internal.misc");
+    }
+
+    /**
+     * Run tests with the Add-Opens attribute in the main manifest.
+     */
+    public void testWithAddOpens() throws Exception {
+        runExpectingPass("Main-Class=Test1,Add-Opens=java.base/jdk.internal.misc");
+        runExpectingPass("Main-Class=Test2,Add-Opens=java.base/jdk.internal.misc");
+
+        // run with leading and trailing spaces
+        runExpectingPass("Main-Class=Test1,Add-Opens=  java.base/jdk.internal.misc");
+        runExpectingPass("Main-Class=Test1,Add-Opens=java.base/jdk.internal.misc  ");
+
+        // run with multiple values
+        runExpectingPass("Main-Class=Test1,Add-Opens=java.base/jdk.internal.misc"
+                + " java.base/jdk.internal.loader");
+        runExpectingPass("Main-Class=Test1,Add-Opens=java.base/jdk.internal.loader"
+                + " java.base/jdk.internal.misc");
+
+        // run with duplicate values
+        runExpectingPass("Main-Class=Test1,Add-Opens=java.base/jdk.internal.misc"
+                + " java.base/jdk.internal.misc");
+    }
+
+    /**
+     * Run tests a bad module or package name
+     */
+    public void testWithBadModuleOrPackage() throws Exception {
+        // Add-Exports with bad module name
+        String attrs = "Main-Class=Test1,Add-Exports=java.DoesNotExist/jdk.internal.misc";
+        runExpectingFail(attrs, "IllegalAccessError");
+
+        // Add-Exports with bad package name
+        attrs = "Main-Class=Test1,Add-Exports=java.base/jdk.internal.DoesNotExit";
+        runExpectingFail(attrs, "IllegalAccessError");
+
+        // Add-Opens with bad module name
+        attrs = "Main-Class=Test1,Add-Opens=java.DoesNotExist/jdk.internal.misc";
+        runExpectingFail(attrs, "IllegalAccessError");
+
+        // Add-Opens with bad package name
+        attrs = "Main-Class=Test1,Add-Opens=java.base/jdk.internal.DoesNotExit";
+        runExpectingFail(attrs, "IllegalAccessError");
+    }
+
+}
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/jdk/test/tools/launcher/modules/addexports/manifest/Test1.java
similarity index 85%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to jdk/test/tools/launcher/modules/addexports/manifest/Test1.java
index 242f168..1d9aaf6 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/jdk/test/tools/launcher/modules/addexports/manifest/Test1.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -21,5 +21,10 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+import jdk.internal.misc.Unsafe;
+
+public class Test1 {
+    public static void main(String[] args) throws Exception {
+        Unsafe unsafe = Unsafe.getUnsafe();
+    }
+}
diff --git a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java b/jdk/test/tools/launcher/modules/addexports/manifest/Test2.java
similarity index 73%
rename from hotspot/test/serviceability/jdwp/JdwpCanReadReply.java
rename to jdk/test/tools/launcher/modules/addexports/manifest/Test2.java
index 438f741..2d9fba1 100644
--- a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java
+++ b/jdk/test/tools/launcher/modules/addexports/manifest/Test2.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -20,22 +20,18 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-import java.io.DataInputStream;
-import java.io.IOException;
+
+import java.lang.reflect.Field;
 
 /**
- * The reply to the JDWP CANREAD command
+ * Use core reflection and setAccessible(true) to access private field.
  */
-public class JdwpCanReadReply extends JdwpReply {
 
-    private boolean canRead;
-
-    protected void parseData(DataInputStream ds) throws IOException {
-        canRead = (ds.read() != 0);
+public class Test2 {
+    public static void main(String[] args) throws Exception {
+        Class<?> c = Class.forName("jdk.internal.misc.Unsafe");
+        Field f = c.getDeclaredField("theUnsafe");
+        f.setAccessible(true);
+        Object unsafe = f.get(null);
     }
-
-    public boolean canRead() {
-        return canRead;
-    }
-
 }
diff --git a/jdk/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java b/jdk/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java
index 6efbbdf..e3d3936 100644
--- a/jdk/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java
+++ b/jdk/test/tools/launcher/modules/addexports/src/m1/jdk/test1/Main.java
@@ -23,13 +23,10 @@
 
 package jdk.test1;
 
-import java.lang.reflect.Field;
 import jdk.internal.misc.Unsafe;
 
 public class Main {
     public static void main(String[] args) throws Exception {
-        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
-        theUnsafe.setAccessible(true);
-        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
+        Unsafe unsafe = Unsafe.getUnsafe();
     }
 }
diff --git a/jdk/test/tools/launcher/modules/listmods/ListModsTest.java b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java
index 793e12e..eb21d2d 100644
--- a/jdk/test/tools/launcher/modules/listmods/ListModsTest.java
+++ b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java
@@ -115,7 +115,7 @@
                 .outputTo(System.out)
                 .errorTo(System.out);
         output.shouldNotContain("java.base");
-        output.shouldNotContain("java.rhubarb");
+        output.shouldContain("java.rhubarb not observable");
         assertTrue(output.getExitValue() == 0);
     }
 
diff --git a/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/module-info.java b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/module-info.java
index 746ce3f..b5fdfea 100644
--- a/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/module-info.java
+++ b/jdk/test/tools/launcher/modules/upgrademodulepath/src/java.transaction/module-info.java
@@ -22,6 +22,6 @@
  */
 
 module java.transaction {
-    requires public java.enterprise;
+    requires transitive java.enterprise;
     exports javax.transaction;
 }
diff --git a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java
index ac54c14..144405e 100644
--- a/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java
+++ b/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,6 @@
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.CompilationID_attribute;
-import com.sun.tools.classfile.ConcealedPackages_attribute;
 import com.sun.tools.classfile.ConstantPool;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info;
@@ -65,8 +64,6 @@
 import com.sun.tools.classfile.EnclosingMethod_attribute;
 import com.sun.tools.classfile.Exceptions_attribute;
 import com.sun.tools.classfile.Field;
-import com.sun.tools.classfile.Hashes_attribute;
-import com.sun.tools.classfile.Hashes_attribute.Entry;
 import com.sun.tools.classfile.InnerClasses_attribute;
 import com.sun.tools.classfile.InnerClasses_attribute.Info;
 import com.sun.tools.classfile.Instruction;
@@ -74,13 +71,18 @@
 import com.sun.tools.classfile.LineNumberTable_attribute;
 import com.sun.tools.classfile.LocalVariableTable_attribute;
 import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
-import com.sun.tools.classfile.MainClass_attribute;
 import com.sun.tools.classfile.Method;
 import com.sun.tools.classfile.MethodParameters_attribute;
 import com.sun.tools.classfile.Module_attribute;
 import com.sun.tools.classfile.Module_attribute.ExportsEntry;
 import com.sun.tools.classfile.Module_attribute.ProvidesEntry;
 import com.sun.tools.classfile.Module_attribute.RequiresEntry;
+import com.sun.tools.classfile.ModuleHashes_attribute;
+import com.sun.tools.classfile.ModuleHashes_attribute.Entry;
+import com.sun.tools.classfile.ModuleMainClass_attribute;
+import com.sun.tools.classfile.ModuleTarget_attribute;
+import com.sun.tools.classfile.ModulePackages_attribute;
+import com.sun.tools.classfile.ModuleVersion_attribute;
 import com.sun.tools.classfile.Opcode;
 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
@@ -102,11 +104,9 @@
 import com.sun.tools.classfile.StackMapTable_attribute.same_locals_1_stack_item_frame_extended;
 import com.sun.tools.classfile.StackMap_attribute;
 import com.sun.tools.classfile.Synthetic_attribute;
-import com.sun.tools.classfile.TargetPlatform_attribute;
 import com.sun.tools.classfile.TypeAnnotation;
 import com.sun.tools.classfile.TypeAnnotation.Position;
 import static com.sun.tools.classfile.TypeAnnotation.TargetType.THROWS;
-import com.sun.tools.classfile.Version_attribute;
 import java.io.*;
 import java.util.*;
 import java.util.jar.JarEntry;
@@ -1017,7 +1017,7 @@
     }
 
     @Override
-    public Element visitConcealedPackages(ConcealedPackages_attribute attr, Element p) {
+    public Element visitModulePackages(ModulePackages_attribute attr, Element p) {
         Element e = new Element(x.getCpString(attr.attribute_name_index));
         for (int i : attr.packages_index) {
             Element ee = new Element("Package");
@@ -1128,7 +1128,7 @@
         for (ExportsEntry export : exports) {
             Element exto = new Element("exports");
             exto.setAttr("package", x.getCpString(export.exports_index));
-            for ( int idx : export.exports_to_index) {
+            for (int idx : export.exports_to_index) {
                 exto.setAttr("module", x.getCpString(idx));
             }
             ex.add(exto);
@@ -1140,7 +1140,9 @@
         Element ex = new Element("Provides");
         for (ProvidesEntry provide : provides) {
             ex.setAttr("provides", x.getCpString(provide.provides_index));
-            ex.setAttr("with", x.getCpString(provide.with_index));
+            for (int idx : provide.with_index) {
+                ex.setAttr("with", x.getCpString(idx));
+            }
         }
         p.add(ex);
     }
@@ -1461,14 +1463,20 @@
     }
 
     @Override
-    public Element visitHashes(Hashes_attribute attr, Element p) {
+    public Element visitModuleHashes(ModuleHashes_attribute attr, Element p) {
         Element e = new Element(x.getCpString(attr.attribute_name_index));
         e.setAttr("Algorithm", x.getCpString(attr.algorithm_index));
         for (Entry entry : attr.hashes_table) {
             Element ee = new Element("Entry");
-            String requires = x.getCpString(entry.requires_index);
-            String hashValue = x.getCpString(entry.hash_index);
-            ee.setAttr(requires, hashValue);
+            String mn = x.getCpString(entry.module_name_index);
+            ee.setAttr("module_name", mn);
+            ee.setAttr("hash_length", "" + entry.hash.length);
+            StringBuilder sb = new StringBuilder();
+            for (byte b: entry.hash) {
+                sb.append(String.format("%02x", b & 0xff));
+            }
+            ee.setAttr("hash", sb.toString());
+            ee.trimToSize();
             e.add(ee);
         }
         e.trimToSize();
@@ -1478,7 +1486,7 @@
     }
 
     @Override
-    public Element visitMainClass(MainClass_attribute attr, Element p) {
+    public Element visitModuleMainClass(ModuleMainClass_attribute attr, Element p) {
         Element e = new Element(x.getCpString(attr.attribute_name_index));
         e.add(x.getCpString(attr.main_class_index));
         e.trimToSize();
@@ -1487,7 +1495,7 @@
     }
 
     @Override
-    public Element visitTargetPlatform(TargetPlatform_attribute attr, Element p) {
+    public Element visitModuleTarget(ModuleTarget_attribute attr, Element p) {
         Element e = new Element(x.getCpString(attr.attribute_name_index));
         e.add(x.getCpString(attr.os_name_index));
         e.add(x.getCpString(attr.os_arch_index));
@@ -1498,7 +1506,7 @@
     }
 
     @Override
-    public Element visitVersion(Version_attribute attr, Element p) {
+    public Element visitModuleVersion(ModuleVersion_attribute attr, Element p) {
         Element e = new Element(x.getCpString(attr.attribute_name_index));
         e.add(x.getCpString(attr.version_index));
         e.trimToSize();
@@ -1813,7 +1821,7 @@
 
     @Override
     public Element visitArray(Array_element_value a, Element p) {
-     Element el = new Element("Array");
+        Element el = new Element("Array");
         for (Annotation.element_value v : a.values) {
            Element child = visit(v, el);
            if (child != null) {
diff --git a/langtools/.hgignore b/langtools/.hgignore
index 3e5642a..d29603e 100644
--- a/langtools/.hgignore
+++ b/langtools/.hgignore
@@ -3,5 +3,4 @@
 ^webrev
 ^.idea
 /nbproject/private/
-^.hgtip
 .DS_Store
diff --git a/langtools/.hgtags b/langtools/.hgtags
index b904c05..603a214 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -389,3 +389,4 @@
 47871e348144bafddea0ede3a44299461e254a2d jdk-9+144
 cb9e896265ef45295fdd09986dee76624e4d41e4 jdk-9+145
 26f972dc2d174a75bc32131c29661c78568586b0 jdk-9+146
+76389430a13e82a9321cdc085216f6bff526e316 jdk-9+147
diff --git a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java
index 306bf82..f560774 100644
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java
@@ -96,10 +96,12 @@
      * @since 9
      */
     enum DirectiveKind {
-        /** A "requires [public] module-name" directive. */
+        /** A "requires (static|transitive)* module-name" directive. */
         REQUIRES,
         /** An "exports package-name [to module-name-list]" directive. */
         EXPORTS,
+        /** An "opens package-name [to module-name-list]" directive. */
+        OPENS,
         /** A "uses service-name" directive. */
         USES,
         /** A "provides service-name with implementation-name" directive. */
@@ -127,10 +129,16 @@
      */
     interface RequiresDirective extends Directive {
         /**
-         * Returns whether or not this is a public dependency.
-         * @return whether or not this is a public dependency
+         * Returns whether or not this is a static dependency.
+         * @return whether or not this is a static dependency
          */
-        boolean isPublic();
+        boolean isStatic();
+
+        /**
+         * Returns whether or not this is a transitive dependency.
+         * @return whether or not this is a transitive dependency
+         */
+        boolean isTransitive();
 
         /**
          * Returns the module that is required
@@ -144,6 +152,7 @@
      * @since 9
      */
     interface ExportsDirective extends Directive {
+
         /**
          * Returns the package being exported.
          * @return the package being exported
@@ -160,6 +169,27 @@
     }
 
     /**
+     * An opened package of a module.
+     * @since 9
+     */
+    interface OpensDirective extends Directive {
+
+        /**
+         * Returns the package being opened.
+         * @return the package being opened
+         */
+        PackageElement getPackage();
+
+        /**
+         * Returns the specific modules to which the package is being open
+         * or null, if the package is open all modules which
+         * have readability to this module.
+         * @return the specific modules to which the package is being opened
+         */
+        List<? extends ModuleElement> getTargetModules();
+    }
+
+    /**
      * An implementation of a service provided by a module.
      * @since 9
      */
@@ -171,10 +201,10 @@
         TypeElement getService();
 
         /**
-         * Returns the implementation of the service being provided.
-         * @return the implementation of the service being provided
+         * Returns the implementations of the service being provided.
+         * @return the implementations of the service being provided
          */
-        TypeElement getImplementation();
+        List<? extends TypeElement> getImplementations();
     }
 
     /**
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java
index aeaef2b..9270b2b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ExportsTree.java
@@ -39,11 +39,12 @@
  * @since 9
  */
 public interface ExportsTree extends DirectiveTree {
+
     /**
      * Returns the name of the package to be exported.
      * @return  the name of the package to be exported
      */
-    ExpressionTree getExportName();
+    ExpressionTree getPackageName();
 
     /**
      * Returns the names of the modules to which the package is exported,
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java
index bcfa6ef..c9f5392 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ModuleTree.java
@@ -33,7 +33,8 @@
  *
  * For example:
  * <pre>
- *    module <em>module-name</em> {
+ *    <em>annotations</em>
+ *    [open] module <em>module-name</em> {
  *        <em>directives</em>
  *    }
  * </pre>
@@ -42,6 +43,18 @@
  */
 public interface ModuleTree extends Tree {
     /**
+     * Returns the annotations associated with this module declaration.
+     * @return the annotations
+     */
+    List<? extends AnnotationTree> getAnnotations();
+
+    /**
+     * Returns the type of this module.
+     * @return the type of this module
+     */
+    ModuleKind getModuleType();
+
+    /**
      * Returns the name of the module.
      * @return the name of the module
      */
@@ -52,4 +65,19 @@
      * @return the directives in the module declaration
      */
     List<? extends DirectiveTree> getDirectives();
+
+    /**
+     * The kind of the module.
+     */
+    enum ModuleKind {
+        /**
+         * Open module.
+         */
+        OPEN,
+        /**
+         * Strong module.
+         */
+        STRONG;
+    }
+
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/OpensTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/OpensTree.java
new file mode 100644
index 0000000..7ccb4bb
--- /dev/null
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/OpensTree.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.tree;
+
+import java.util.List;
+
+/**
+ * A tree node for an 'opens' directive in a module declaration.
+ *
+ * For example:
+ * <pre>
+ *    opens   <em>package-name</em>;
+ *    opens   <em>package-name</em> to <em>module-name</em>;
+ * </pre>
+ *
+ * @since 9
+ */
+public interface OpensTree extends DirectiveTree {
+
+    /**
+     * Returns the name of the package to be opened.
+     * @return  the name of the package to be opened
+     */
+    ExpressionTree getPackageName();
+
+    /**
+     * Returns the names of the modules to which the package is opened,
+     * or null, if the package is opened to all modules.
+     *
+     * @return the names of the modules to which the package is opened, or null
+     */
+    List<? extends ExpressionTree> getModuleNames();
+}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java
index 3189f3f..fa22f3b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ProvidesTree.java
@@ -25,6 +25,8 @@
 
 package com.sun.source.tree;
 
+import java.util.List;
+
 /**
  * A tree node for a 'provides' directive in a module declaration.
  *
@@ -43,8 +45,8 @@
     ExpressionTree getServiceName();
 
     /**
-     * Returns the name of the implementation type being provided.
-     * @return the name of the implementation type being provided
+     * Returns the names of the implementation types being provided.
+     * @return the names of the implementation types being provided
      */
-    ExpressionTree getImplementationName();
+    List<? extends ExpressionTree> getImplementationNames();
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java
index 9a5f55c..c7c7dd8 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/RequiresTree.java
@@ -31,17 +31,24 @@
  * For example:
  * <pre>
  *    requires <em>module-name</em>;
- *    requires public <em>module-name</em>;
+ *    requires static <em>module-name</em>;
+ *    requires transitive <em>module-name</em>;
  * </pre>
  *
  * @since 9
  */
 public interface RequiresTree extends DirectiveTree {
     /**
-     * Returns true if this is a "requires public" directive.
-     * @return true if this is a "requires public" directive
+     * Returns true if this is a "requires static" directive.
+     * @return true if this is a "requires static" directive
      */
-    boolean isPublic();
+    boolean isStatic();
+
+    /**
+     * Returns true if this is a "requires transitive" directive.
+     * @return true if this is a "requires transitive" directive
+     */
+    boolean isTransitive();
 
     /**
      * Returns the name of the module that is required.
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
index 73f1fd4..0cd1780 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -610,25 +610,31 @@
 
         /**
          * Used for instances of {@link ExportsTree} representing
-         * export directives in a module declaration.
+         * exports directives in a module declaration.
          */
         EXPORTS(ExportsTree.class),
 
         /**
+         * Used for instances of {@link ExportsTree} representing
+         * opens directives in a module declaration.
+         */
+        OPENS(OpensTree.class),
+
+        /**
          * Used for instances of {@link ProvidesTree} representing
-         * export directives in a module declaration.
+         * provides directives in a module declaration.
          */
         PROVIDES(ProvidesTree.class),
 
         /**
          * Used for instances of {@link RequiresTree} representing
-         * export directives in a module declaration.
+         * requires directives in a module declaration.
          */
         REQUIRES(RequiresTree.class),
 
         /**
          * Used for instances of {@link UsesTree} representing
-         * export directives in a module declaration.
+         * uses directives in a module declaration.
          */
         USES(UsesTree.class),
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
index f1f951e..3d615e4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
@@ -498,6 +498,14 @@
     R visitExports(ExportsTree node, P p);
 
     /**
+     * Visits an OpensTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitOpens(OpensTree node, P p);
+
+    /**
      * Visits a ProvidesTree node.
      * @param node the node being visited
      * @param p a parameter value
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
index 0b13ca7..85c88ce 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -729,6 +729,11 @@
     }
 
     @Override
+    public R visitOpens(OpensTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    @Override
     public R visitProvides(ProvidesTree node, P p) {
         return defaultAction(node, p);
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
index 3751154..7ba5957 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -846,28 +846,41 @@
         return r;
     }
 
+    @Override
     public R visitModule(ModuleTree node, P p) {
-        R r = scan(node.getName(), p);
+        R r = scan(node.getAnnotations(), p);
+        r = scanAndReduce(node.getName(), p, r);
         r = scanAndReduce(node.getDirectives(), p, r);
         return r;
     }
 
+    @Override
     public R visitExports(ExportsTree node, P p) {
-        R r = scan(node.getExportName(), p);
+        R r = scan(node.getPackageName(), p);
         r = scanAndReduce(node.getModuleNames(), p, r);
         return r;
     }
 
-    public R visitProvides(ProvidesTree node, P p) {
-        R r = scan(node.getServiceName(), p);
-        r = scanAndReduce(node.getImplementationName(), p, r);
+    @Override
+    public R visitOpens(OpensTree node, P p) {
+        R r = scan(node.getPackageName(), p);
+        r = scanAndReduce(node.getModuleNames(), p, r);
         return r;
     }
 
+    @Override
+    public R visitProvides(ProvidesTree node, P p) {
+        R r = scan(node.getServiceName(), p);
+        r = scanAndReduce(node.getImplementationNames(), p, r);
+        return r;
+    }
+
+    @Override
     public R visitRequires(RequiresTree node, P p) {
         return scan(node.getModuleName(), p);
     }
 
+    @Override
     public R visitUses(UsesTree node, P p) {
         return scan(node.getServiceName(), p);
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
index 7cccabe..5335187 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
@@ -29,13 +29,16 @@
 import java.nio.file.Path;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
 
@@ -558,17 +561,17 @@
 
         if (wantClassFiles && (classLocn != null)) {
             fillIn(p, classLocn,
-                   fileManager.list(classLocn,
-                                    packageName,
-                                    classKinds,
-                                    false));
+                   list(classLocn,
+                        p,
+                        packageName,
+                        classKinds));
         }
         if (wantSourceFiles && (sourceLocn != null)) {
             fillIn(p, sourceLocn,
-                   fileManager.list(sourceLocn,
-                                    packageName,
-                                    sourceKinds,
-                                    false));
+                   list(sourceLocn,
+                        p,
+                        packageName,
+                        sourceKinds));
         }
     }
 
@@ -620,23 +623,23 @@
         String packageName = p.fullname.toString();
         if (wantSourceFiles && !haveSourcePath) {
             fillIn(p, CLASS_PATH,
-                   fileManager.list(CLASS_PATH,
-                                    packageName,
-                                    kinds,
-                                    false));
+                   list(CLASS_PATH,
+                        p,
+                        packageName,
+                        kinds));
         } else {
             if (wantClassFiles)
                 fillIn(p, CLASS_PATH,
-                       fileManager.list(CLASS_PATH,
-                                        packageName,
-                                        classKinds,
-                                        false));
+                       list(CLASS_PATH,
+                            p,
+                            packageName,
+                            classKinds));
             if (wantSourceFiles)
                 fillIn(p, SOURCE_PATH,
-                       fileManager.list(SOURCE_PATH,
-                                        packageName,
-                                        sourceKinds,
-                                        false));
+                       list(SOURCE_PATH,
+                            p,
+                            packageName,
+                            sourceKinds));
         }
     }
 
@@ -645,12 +648,12 @@
      */
     private void scanPlatformPath(PackageSymbol p) throws IOException {
         fillIn(p, PLATFORM_CLASS_PATH,
-               fileManager.list(PLATFORM_CLASS_PATH,
-                                p.fullname.toString(),
-                                allowSigFiles ? EnumSet.of(JavaFileObject.Kind.CLASS,
-                                                           JavaFileObject.Kind.OTHER)
-                                              : EnumSet.of(JavaFileObject.Kind.CLASS),
-                                false));
+               list(PLATFORM_CLASS_PATH,
+                    p,
+                    p.fullname.toString(),
+                    allowSigFiles ? EnumSet.of(JavaFileObject.Kind.CLASS,
+                                               JavaFileObject.Kind.OTHER)
+                                  : EnumSet.of(JavaFileObject.Kind.CLASS)));
     }
     // where
         @SuppressWarnings("fallthrough")
@@ -662,10 +665,7 @@
             for (JavaFileObject fo : files) {
                 switch (fo.getKind()) {
                 case OTHER:
-                    boolean sigFile = location == PLATFORM_CLASS_PATH &&
-                                      allowSigFiles &&
-                                      fo.getName().endsWith(".sig");
-                    if (!sigFile) {
+                    if (!isSigFile(location, fo)) {
                         extraFileActions(p, fo);
                         break;
                     }
@@ -682,10 +682,61 @@
                 }
                 default:
                     extraFileActions(p, fo);
+                    break;
                 }
             }
         }
 
+        boolean isSigFile(Location location, JavaFileObject fo) {
+            return location == PLATFORM_CLASS_PATH &&
+                   allowSigFiles &&
+                   fo.getName().endsWith(".sig");
+        }
+
+        Iterable<JavaFileObject> list(Location location,
+                                      PackageSymbol p,
+                                      String packageName,
+                                      Set<Kind> kinds) throws IOException {
+            Iterable<JavaFileObject> listed = fileManager.list(location,
+                                                               packageName,
+                                                               EnumSet.allOf(Kind.class),
+                                                               false);
+            return () -> new Iterator<JavaFileObject>() {
+                private final Iterator<JavaFileObject> original = listed.iterator();
+                private JavaFileObject next;
+                @Override
+                public boolean hasNext() {
+                    if (next == null) {
+                        while (original.hasNext()) {
+                            JavaFileObject fo = original.next();
+
+                            if (fo.getKind() != Kind.CLASS &&
+                                fo.getKind() != Kind.SOURCE &&
+                                !isSigFile(currentLoc, fo)) {
+                                p.flags_field |= Flags.HAS_RESOURCE;
+                            }
+
+                            if (kinds.contains(fo.getKind())) {
+                                next = fo;
+                                break;
+                            }
+                        }
+                    }
+                    return next != null;
+                }
+
+                @Override
+                public JavaFileObject next() {
+                    if (!hasNext())
+                        throw new NoSuchElementException();
+                    JavaFileObject result = next;
+                    next = null;
+                    return result;
+                }
+
+            };
+        }
+
     /**
      * Used for bad class definition files, such as bad .class files or
      * for .java files with unexpected package or class names.
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
index 7fc0ffa..e8ae0be 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Directive.java
@@ -53,7 +53,8 @@
 
     /** Flags for RequiresDirective. */
     public enum RequiresFlag {
-        PUBLIC(0x0020),
+        TRANSITIVE(0x0010),
+        STATIC_PHASE(0x0020),
         SYNTHETIC(0x1000),
         MANDATED(0x8000),
         EXTRA(0x10000);
@@ -73,17 +74,44 @@
         public final int value;
     }
 
+    /** Flags for ExportsDirective. */
+    public enum ExportsFlag {
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000);
+
+        // overkill? move to ClassWriter?
+        public static int value(Set<ExportsFlag> s) {
+            int v = 0;
+            for (ExportsFlag f: s)
+                v |= f.value;
+            return v;
+        }
+
+        ExportsFlag(int value) {
+            this.value = value;
+        }
+
+        public final int value;
+    }
+
     /**
      * 'exports' Package ';'
+     * 'exports' Package 'to' ModuleList ';'
      */
     public static class ExportsDirective extends Directive
             implements ModuleElement.ExportsDirective {
         public final PackageSymbol packge;
         public final List<ModuleSymbol> modules;
+        public final Set<ExportsFlag> flags;
 
         public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
+            this(packge, modules, EnumSet.noneOf(ExportsFlag.class));
+        }
+
+        public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<ExportsFlag> flags) {
             this.packge = packge;
             this.modules = modules;
+            this.flags = flags;
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
@@ -92,12 +120,12 @@
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public PackageElement getPackage() {
+        public PackageSymbol getPackage() {
             return packge;
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public java.util.List<? extends ModuleElement> getTargetModules() {
+        public java.util.List<ModuleSymbol> getTargetModules() {
             return modules == null
                     ? null
                     : Collections.unmodifiableList(modules);
@@ -112,17 +140,83 @@
         }
     }
 
+    /** Flags for OpensDirective. */
+    public enum OpensFlag {
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000);
+
+        // overkill? move to ClassWriter?
+        public static int value(Set<OpensFlag> s) {
+            int v = 0;
+            for (OpensFlag f: s)
+                v |= f.value;
+            return v;
+        }
+
+        OpensFlag(int value) {
+            this.value = value;
+        }
+
+        public final int value;
+    }
+
+    /**
+     * 'opens' Package ';'
+     * 'opens' Package 'to' ModuleList ';'
+     */
+    public static class OpensDirective extends Directive
+            implements ModuleElement.OpensDirective {
+        public final PackageSymbol packge;
+        public final List<ModuleSymbol> modules;
+        public final Set<OpensFlag> flags;
+
+        public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
+            this(packge, modules, EnumSet.noneOf(OpensFlag.class));
+        }
+
+        public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<OpensFlag> flags) {
+            this.packge = packge;
+            this.modules = modules;
+            this.flags = flags;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleElement.DirectiveKind getKind() {
+            return ModuleElement.DirectiveKind.OPENS;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public PackageSymbol getPackage() {
+            return packge;
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public java.util.List<ModuleSymbol> getTargetModules() {
+            return modules == null
+                    ? null
+                    : Collections.unmodifiableList(modules);
+        }
+
+        @Override
+        public String toString() {
+            if (modules == null)
+                return "Opens[" + packge + "]";
+            else
+                return "Opens[" + packge + ":" + modules + "]";
+        }
+    }
+
     /**
      * 'provides' ServiceName 'with' QualifiedIdentifer ';'
      */
     public static class ProvidesDirective extends Directive
             implements ModuleElement.ProvidesDirective {
         public final ClassSymbol service;
-        public final ClassSymbol impl;
+        public final List<ClassSymbol> impls;
 
-        public ProvidesDirective(ClassSymbol service, ClassSymbol impl) {
+        public ProvidesDirective(ClassSymbol service, List<ClassSymbol> impls) {
             this.service = service;
-            this.impl = impl;
+            this.impls = impls;
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
@@ -131,37 +225,39 @@
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public TypeElement getService() {
+        public ClassSymbol getService() {
             return service;
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public TypeElement getImplementation() {
-            return impl;
+        public List<ClassSymbol> getImplementations() {
+            return impls;
         }
 
         @Override
         public String toString() {
-            return "Provides[" + service + "," + impl + "]";
+            return "Provides[" + service + "," + impls + "]";
         }
 
+        // TODO: delete?
         @Override
         public boolean equals(Object obj) {
             if (!(obj instanceof ProvidesDirective)) {
                 return false;
             }
             ProvidesDirective other = (ProvidesDirective)obj;
-            return service == other.service && impl == other.impl;
+            return service == other.service && impls.equals(other.impls);
         }
 
+        // TODO: delete?
         @Override
         public int hashCode() {
-            return service.hashCode() * 31 + impl.hashCode() * 37;
+            return service.hashCode() * 31 + impls.hashCode() * 37;
         }
     }
 
     /**
-     * 'requires' ['public'] ModuleName ';'
+     * 'requires' ('static' | 'transitive')* ModuleName ';'
      */
     public static class RequiresDirective extends Directive
             implements ModuleElement.RequiresDirective {
@@ -183,12 +279,17 @@
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public boolean isPublic() {
-            return flags.contains(RequiresFlag.PUBLIC);
+        public boolean isStatic() {
+            return flags.contains(RequiresFlag.STATIC_PHASE);
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public ModuleElement getDependency() {
+        public boolean isTransitive() {
+            return flags.contains(RequiresFlag.TRANSITIVE);
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public ModuleSymbol getDependency() {
             return module;
         }
 
@@ -215,7 +316,7 @@
         }
 
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
-        public TypeElement getService() {
+        public ClassSymbol getService() {
             return service;
         }
 
@@ -224,6 +325,7 @@
             return "Uses[" + service + "]";
         }
 
+        // TODO: delete?
         @Override
         public boolean equals(Object obj) {
             if (!(obj instanceof UsesDirective)) {
@@ -233,6 +335,7 @@
             return service == other.service;
         }
 
+        // TODO: delete?
         @Override
         public int hashCode() {
             return service.hashCode() * 31;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
index 16185f2..503e430 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
@@ -294,9 +294,19 @@
     public static final long SYSTEM_MODULE = 1L<<53;
 
     /**
+     * Flag to indicate the given symbol has a @Deprecated annotation.
+     */
+    public static final long DEPRECATED_ANNOTATION = 1L<<54;
+
+    /**
      * Flag to indicate the given symbol has been deprecated and marked for removal.
      */
-    public static final long DEPRECATED_REMOVAL = 1L<<54;
+    public static final long DEPRECATED_REMOVAL = 1L<<55;
+
+    /**
+     * Flag to indicate the given PackageSymbol contains any non-.java and non-.class resources.
+     */
+    public static final long HAS_RESOURCE = 1L<<56;
 
     /** Modifier masks.
      */
@@ -408,7 +418,11 @@
         LAMBDA_METHOD(Flags.LAMBDA_METHOD),
         TYPE_TRANSLATED(Flags.TYPE_TRANSLATED),
         MODULE(Flags.MODULE),
-        DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL);
+        AUTOMATIC_MODULE(Flags.AUTOMATIC_MODULE),
+        SYSTEM_MODULE(Flags.SYSTEM_MODULE),
+        DEPRECATED_ANNOTATION(Flags.DEPRECATED_ANNOTATION),
+        DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL),
+        HAS_RESOURCE(Flags.HAS_RESOURCE);
 
         Flag(long flag) {
             this.value = flag;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java
index 5b7d30c..dc93c65 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Scope.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
index 4c3ca38..1e713f0 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
@@ -28,6 +28,7 @@
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Inherited;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -47,6 +48,7 @@
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.code.ClassFinder.BadEnclosingMethodAttr;
+import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Kinds.Kind;
 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
 import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -359,6 +361,10 @@
         return (flags_field & DEPRECATED) != 0;
     }
 
+    public boolean hasDeprecatedAnnotation() {
+        return (flags_field & DEPRECATED_ANNOTATION) != 0;
+    }
+
     public boolean isDeprecatedForRemoval() {
         return (flags_field & DEPRECATED_REMOVAL) != 0;
     }
@@ -907,6 +913,7 @@
         public List<com.sun.tools.javac.code.Directive> directives;
         public List<com.sun.tools.javac.code.Directive.RequiresDirective> requires;
         public List<com.sun.tools.javac.code.Directive.ExportsDirective> exports;
+        public List<com.sun.tools.javac.code.Directive.OpensDirective> opens;
         public List<com.sun.tools.javac.code.Directive.ProvidesDirective> provides;
         public List<com.sun.tools.javac.code.Directive.UsesDirective> uses;
 
@@ -917,6 +924,7 @@
         public List<Symbol> enclosedPackages = List.nil();
 
         public Completer usesProvidesCompleter = Completer.NULL_COMPLETER;
+        public final Set<ModuleFlags> flags = EnumSet.noneOf(ModuleFlags.class);
 
         /**
          * Create a ModuleSymbol with an associated module-info ClassSymbol.
@@ -942,6 +950,11 @@
             return name.isEmpty() && owner == null;
         }
 
+        @Override
+        public boolean isDeprecated() {
+            return hasDeprecatedAnnotation();
+        }
+
         public boolean isNoModule() {
             return false;
         }
@@ -1007,6 +1020,26 @@
 
     }
 
+    public enum ModuleFlags {
+        OPEN(0x0020),
+        SYNTHETIC(0x1000),
+        MANDATED(0x8000);
+
+        public static int value(Set<ModuleFlags> s) {
+            int v = 0;
+            for (ModuleFlags f: s)
+                v |= f.value;
+            return v;
+        }
+
+        private ModuleFlags(int value) {
+            this.value = value;
+        }
+
+        public final int value;
+
+    }
+
     /** A class for package symbols
      */
     public static class PackageSymbol extends TypeSymbol
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
index 2dd0013..1cbeadb 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
@@ -1869,6 +1869,12 @@
      */
     public static class UndetVar extends DelegatedType {
 
+        enum Kind {
+            NORMAL,
+            CAPTURED,
+            THROWS;
+        }
+
         /** Inference variable change listener. The listener method is called
          *  whenever a change to the inference variable's bounds occurs
          */
@@ -1929,6 +1935,8 @@
         /** inference variable's change listener */
         public UndetVarListener listener = null;
 
+        Kind kind;
+
         @Override
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitUndetVar(this, s);
@@ -1937,6 +1945,9 @@
         public UndetVar(TypeVar origin, UndetVarListener listener, Types types) {
             // This is a synthesized internal type, so we cannot annotate it.
             super(UNDETVAR, origin);
+            this.kind = origin.isCaptured() ?
+                    Kind.CAPTURED :
+                    Kind.NORMAL;
             this.listener = listener;
             bounds = new EnumMap<>(InferenceBound.class);
             List<Type> declaredBounds = types.getBounds(origin);
@@ -1948,6 +1959,10 @@
                 //add bound works in reverse order
                 addBound(InferenceBound.UPPER, t, types, true);
             }
+            if (origin.isCaptured() && !origin.lower.hasTag(BOT)) {
+                //add lower bound if needed
+                addBound(InferenceBound.LOWER, origin.lower, types, true);
+            }
         }
 
         @DefinedBy(Api.LANGUAGE_MODEL)
@@ -1977,6 +1992,14 @@
             return result;
         }
 
+        public void setThrow() {
+            if (this.kind == Kind.CAPTURED) {
+                //invalid state transition
+                throw new IllegalStateException();
+            }
+            this.kind = Kind.THROWS;
+        }
+
         /**
          * Returns a new copy of this undet var.
          */
@@ -2062,17 +2085,29 @@
             addBound(ib, bound, types, false);
         }
 
-        protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
-            Type bound2 = bound.map(toTypeVarMap).baseType();
-            List<Type> prevBounds = bounds.get(ib);
-            if (bound == qtype) return;
-            for (Type b : prevBounds) {
-                //check for redundancy - use strict version of isSameType on tvars
-                //(as the standard version will lead to false positives w.r.t. clones ivars)
-                if (types.isSameType(b, bound2, true)) return;
+        @SuppressWarnings("fallthrough")
+        private void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
+            if (kind == Kind.CAPTURED && !update) {
+                //Captured inference variables bounds must not be updated during incorporation,
+                //except when some inference variable (beta) has been instantiated in the
+                //right-hand-side of a 'C<alpha> = capture(C<? extends/super beta>) constraint.
+                if (bound.hasTag(UNDETVAR) && !((UndetVar)bound).isCaptured()) {
+                    //If the new incoming bound is itself a (regular) inference variable,
+                    //then we are allowed to propagate this inference variable bounds to it.
+                    ((UndetVar)bound).addBound(ib.complement(), this, types, false);
+                }
+            } else {
+                Type bound2 = bound.map(toTypeVarMap).baseType();
+                List<Type> prevBounds = bounds.get(ib);
+                if (bound == qtype) return;
+                for (Type b : prevBounds) {
+                    //check for redundancy - use strict version of isSameType on tvars
+                    //(as the standard version will lead to false positives w.r.t. clones ivars)
+                    if (types.isSameType(b, bound2, true)) return;
+                }
+                bounds.put(ib, prevBounds.prepend(bound2));
+                notifyBoundChange(ib, bound2, false);
             }
-            bounds.put(ib, prevBounds.prepend(bound2));
-            notifyBoundChange(ib, bound2, false);
         }
         //where
             TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
@@ -2128,46 +2163,12 @@
             }
         }
 
-        public boolean isCaptured() {
-            return false;
-        }
-    }
-
-    /**
-     * This class is used to represent synthetic captured inference variables
-     * that can be generated during nested generic method calls. The only difference
-     * between these inference variables and ordinary ones is that captured inference
-     * variables cannot get new bounds through incorporation.
-     */
-    public static class CapturedUndetVar extends UndetVar {
-
-        public CapturedUndetVar(CapturedType origin, UndetVarListener listener, Types types) {
-            super(origin, listener, types);
-            if (!origin.lower.hasTag(BOT)) {
-                addBound(InferenceBound.LOWER, origin.lower, types, true);
-            }
+        public final boolean isCaptured() {
+            return kind == Kind.CAPTURED;
         }
 
-        @Override
-        public void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
-            if (update) {
-                //only change bounds if request comes from substBounds
-                super.addBound(ib, bound, types, update);
-            }
-            else if (bound.hasTag(UNDETVAR) && !((UndetVar) bound).isCaptured()) {
-                ((UndetVar) bound).addBound(ib.complement(), this, types, false);
-            }
-        }
-
-        @Override
-        public boolean isCaptured() {
-            return true;
-        }
-
-        public UndetVar dup(Types types) {
-            UndetVar uv2 = new CapturedUndetVar((CapturedType)qtype, listener, types);
-            dupTo(uv2, types);
-            return uv2;
+        public final boolean isThrows() {
+            return kind == Kind.THROWS;
         }
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
index 69df6f0..f0bf5f0 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java
@@ -237,6 +237,9 @@
             // TYPE_PARAMETER doesn't aid in distinguishing between
             // Type annotations and declaration annotations on an
             // Element
+        } else if (e.value.name == names.MODULE) {
+            if (s.kind == MDL)
+                return AnnotationType.DECLARATION;
         } else {
             Assert.error("annotationTargetType(): unrecognized Attribute name " + e.value.name +
                     " (" + e.value.name.getClass() + ")");
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
index 574ae10..da01293 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
@@ -45,6 +45,7 @@
 import java.util.*;
 
 import static com.sun.tools.javac.code.Flags.SYNTHETIC;
+import static com.sun.tools.javac.code.Kinds.Kind.MDL;
 import static com.sun.tools.javac.code.Kinds.Kind.MTH;
 import static com.sun.tools.javac.code.Kinds.Kind.VAR;
 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
@@ -337,9 +338,9 @@
 
             // Note: @Deprecated has no effect on local variables and parameters
             if (!c.type.isErroneous()
-                    && toAnnotate.owner.kind != MTH
+                    && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH)
                     && types.isSameType(c.type, syms.deprecatedType)) {
-                toAnnotate.flags_field |= Flags.DEPRECATED;
+                toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
                 Attribute fr = c.member(names.forRemoval);
                 if (fr instanceof Attribute.Constant) {
                     Attribute.Constant v = (Attribute.Constant) fr;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index 3aee3c4..43757ed 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -2494,6 +2494,11 @@
                     List<Type> thrownTypes = resultInfo.checkContext.inferenceContext().asUndetVars(lambdaType.getThrownTypes());
 
                     chk.unhandled(inferredThrownTypes, thrownTypes);
+
+                    //18.2.5: "In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej"
+                    thrownTypes.stream()
+                            .filter(t -> t.hasTag(UNDETVAR))
+                            .forEach(t -> ((UndetVar)t).setThrow());
                 }
 
                 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget);
@@ -3074,6 +3079,10 @@
             if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) {
                 log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes());
             }
+            //18.2.5: "In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej"
+            thrownTypes.stream()
+                    .filter(t -> t.hasTag(UNDETVAR))
+                    .forEach(t -> ((UndetVar)t).setThrow());
         }
     }
 
@@ -4432,6 +4441,17 @@
 
     public void visitModuleDef(JCModuleDecl tree) {
         tree.sym.completeUsesProvides();
+        ModuleSymbol msym = tree.sym;
+        Lint lint = env.outer.info.lint = env.outer.info.lint.augment(msym);
+        Lint prevLint = chk.setLint(lint);
+
+        chk.checkDeprecatedAnnotation(tree, msym);
+
+        try {
+            deferredLintHandler.flush(tree.pos());
+        } finally {
+            chk.setLint(prevLint);
+        }
     }
 
     /** Finish the attribution of a class. */
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index bc1ab5f..8150c6f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -227,10 +227,18 @@
     void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
         if (sym.isDeprecatedForRemoval()) {
             if (!lint.isSuppressed(LintCategory.REMOVAL)) {
-                removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location());
+                if (sym.kind == MDL) {
+                    removalHandler.report(pos, "has.been.deprecated.for.removal.module", sym);
+                } else {
+                    removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location());
+                }
             }
         } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
-            deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
+            if (sym.kind == MDL) {
+                deprecationHandler.report(pos, "has.been.deprecated.module", sym);
+            } else {
+                deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
+            }
         }
     }
 
@@ -3245,7 +3253,7 @@
     void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
         if ( (s.isDeprecatedForRemoval()
                 || s.isDeprecated() && !other.isDeprecated())
-              && s.outermostClass() != other.outermostClass()) {
+                && (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)) {
             deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
                 @Override
                 public void report() {
@@ -3851,7 +3859,7 @@
             }
 
             if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) {
-                //check that relativeTo.modle requires public what.modle, somehow:
+                //check that relativeTo.modle requires transitive what.modle, somehow:
                 List<ModuleSymbol> todo = List.of(inPackage.modle);
 
                 while (todo.nonEmpty()) {
@@ -3860,13 +3868,13 @@
                     if (current == whatPackage.modle)
                         return ; //OK
                     for (RequiresDirective req : current.requires) {
-                        if (req.isPublic()) {
+                        if (req.isTransitive()) {
                             todo = todo.prepend(req.module);
                         }
                     }
                 }
 
-                log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredPublic(kindName(what), what, what.packge().modle));
+                log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredTransitive(kindName(what), what, what.packge().modle));
             }
         }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
index deda2e4..7755567 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
@@ -167,6 +167,9 @@
      */
     ListBuffer<ClassSymbol> uncompleted;
 
+    /** The queue of modules whose imports still need to be checked. */
+    ListBuffer<JCCompilationUnit> unfinishedModules = new ListBuffer<>();
+
     /** A dummy class to serve as enclClass for toplevel environments.
      */
     private JCClassDecl predefClassDef;
@@ -308,6 +311,10 @@
         boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
                                                              JavaFileObject.Kind.SOURCE);
         if (TreeInfo.isModuleInfo(tree)) {
+            JCPackageDecl pd = tree.getPackage();
+            if (pd != null) {
+                log.error(pd.pos(), Errors.NoPkgInModuleInfoJava);
+            }
             tree.packge = syms.rootPackage;
             Env<AttrContext> topEnv = topLevelEnv(tree);
             classEnter(tree.defs, topEnv);
@@ -405,6 +412,17 @@
             if (owner.kind == TYP) {
                 // We are seeing a member class.
                 c = syms.enterClass(env.toplevel.modle, tree.name, (TypeSymbol)owner);
+                if (c.owner != owner) {
+                    //anonymous class loaded from a classfile may be recreated from source (see below)
+                    //if this class is a member of such an anonymous class, fix the owner:
+                    Assert.check(owner.owner.kind != TYP, () -> owner.toString());
+                    Assert.check(c.owner.kind == TYP, () -> c.owner.toString());
+                    ClassSymbol cowner = (ClassSymbol) c.owner;
+                    if (cowner.members_field != null) {
+                        cowner.members_field.remove(c);
+                    }
+                    c.owner = owner;
+                }
                 if ((owner.flags_field & INTERFACE) != 0) {
                     tree.mods.flags |= PUBLIC | STATIC;
                 }
@@ -509,7 +527,9 @@
     public void visitModuleDef(JCModuleDecl tree) {
         Env<AttrContext> moduleEnv = moduleEnv(tree, env);
         typeEnvs.put(tree.sym, moduleEnv);
-        todo.append(moduleEnv);
+        if (modules.isInModuleGraph(tree.sym)) {
+            todo.append(moduleEnv);
+        }
     }
 
     /** Default class enter visitor method: do nothing.
@@ -552,7 +572,19 @@
                         prevUncompleted.append(clazz);
                 }
 
-                typeEnter.ensureImportsChecked(trees);
+                if (!modules.modulesInitialized()) {
+                    for (JCCompilationUnit cut : trees) {
+                        if (cut.getModuleDecl() != null) {
+                            unfinishedModules.append(cut);
+                        } else {
+                            typeEnter.ensureImportsChecked(List.of(cut));
+                        }
+                    }
+                } else {
+                    typeEnter.ensureImportsChecked(unfinishedModules.toList());
+                    unfinishedModules.clear();
+                    typeEnter.ensureImportsChecked(trees);
+                }
             }
         } finally {
             uncompleted = prevUncompleted;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
index 7850fac..289aa4c 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
@@ -627,12 +627,11 @@
     TypeMapping<Void> fromTypeVarFun = new TypeMapping<Void>() {
         @Override
         public Type visitTypeVar(TypeVar tv, Void aVoid) {
-            return new UndetVar(tv, incorporationEngine(), types);
-        }
-
-        @Override
-        public Type visitCapturedType(CapturedType t, Void aVoid) {
-            return new CapturedUndetVar(t, incorporationEngine(), types);
+            UndetVar uv = new UndetVar(tv, incorporationEngine(), types);
+            if ((tv.tsym.flags() & Flags.THROWS) != 0) {
+                uv.setThrow();
+            }
+            return uv;
         }
     };
 
@@ -1463,7 +1462,7 @@
         THROWS(InferenceBound.UPPER) {
             @Override
             public boolean accepts(UndetVar t, InferenceContext inferenceContext) {
-                if ((t.qtype.tsym.flags() & Flags.THROWS) == 0) {
+                if (!t.isThrows()) {
                     //not a throws undet var
                     return false;
                 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
index 0333f73..08b37f7 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
@@ -2387,6 +2387,7 @@
     public void visitModuleDef(JCModuleDecl tree) {
         ModuleSymbol msym = tree.sym;
         ClassSymbol c = msym.module_info;
+        c.setAttributes(msym);
         c.flags_field |= Flags.MODULE;
         createInfoClass(List.<JCAnnotation>nil(), tree.sym.module_info);
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
index e620285..dd32f93 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
@@ -50,9 +50,14 @@
 import javax.tools.JavaFileObject.Kind;
 import javax.tools.StandardLocation;
 
+import com.sun.source.tree.ModuleTree.ModuleKind;
 import com.sun.tools.javac.code.ClassFinder;
+import com.sun.tools.javac.code.DeferredLintHandler;
 import com.sun.tools.javac.code.Directive;
 import com.sun.tools.javac.code.Directive.ExportsDirective;
+import com.sun.tools.javac.code.Directive.ExportsFlag;
+import com.sun.tools.javac.code.Directive.OpensDirective;
+import com.sun.tools.javac.code.Directive.OpensFlag;
 import com.sun.tools.javac.code.Directive.RequiresDirective;
 import com.sun.tools.javac.code.Directive.RequiresFlag;
 import com.sun.tools.javac.code.Directive.UsesDirective;
@@ -66,6 +71,7 @@
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleFlags;
 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symbol.PackageSymbol;
 import com.sun.tools.javac.code.Symtab;
@@ -78,14 +84,18 @@
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCDirective;
 import com.sun.tools.javac.tree.JCTree.JCExports;
 import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
+import com.sun.tools.javac.tree.JCTree.JCOpens;
 import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
 import com.sun.tools.javac.tree.JCTree.JCProvides;
 import com.sun.tools.javac.tree.JCTree.JCRequires;
 import com.sun.tools.javac.tree.JCTree.JCUses;
+import com.sun.tools.javac.tree.JCTree.Tag;
 import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.util.Abort;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JCDiagnostic;
@@ -96,20 +106,15 @@
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.javac.util.Options;
-
-import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
-import static com.sun.tools.javac.code.Kinds.Kind.MDL;
-import static com.sun.tools.javac.code.TypeTag.CLASS;
-
-import com.sun.tools.javac.tree.JCTree.JCDirective;
-import com.sun.tools.javac.tree.JCTree.Tag;
-import com.sun.tools.javac.util.Abort;
 import com.sun.tools.javac.util.Position;
 
 import static com.sun.tools.javac.code.Flags.ABSTRACT;
 import static com.sun.tools.javac.code.Flags.ENUM;
 import static com.sun.tools.javac.code.Flags.PUBLIC;
-import static com.sun.tools.javac.tree.JCTree.Tag.MODULEDEF;
+import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
+import static com.sun.tools.javac.code.Kinds.Kind.MDL;
+import static com.sun.tools.javac.code.Kinds.Kind.MTH;
+import static com.sun.tools.javac.code.TypeTag.CLASS;
 
 /**
  *  TODO: fill in
@@ -127,6 +132,8 @@
     private final Names names;
     private final Symtab syms;
     private final Attr attr;
+    private final Check chk;
+    private final DeferredLintHandler deferredLintHandler;
     private final TypeEnvs typeEnvs;
     private final Types types;
     private final JavaFileManager fileManager;
@@ -169,6 +176,8 @@
         names = Names.instance(context);
         syms = Symtab.instance(context);
         attr = Attr.instance(context);
+        chk = Check.instance(context);
+        deferredLintHandler = DeferredLintHandler.instance(context);
         typeEnvs = TypeEnvs.instance(context);
         moduleFinder = ModuleFinder.instance(context);
         types = Types.instance(context);
@@ -276,6 +285,10 @@
         return defaultModule;
     }
 
+    public boolean modulesInitialized() {
+        return allModules != null;
+    }
+
     private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) {
         Set<ModuleSymbol> modules = new LinkedHashSet<>();
         for (JCCompilationUnit tree : trees) {
@@ -292,9 +305,9 @@
 
     private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set<ModuleSymbol> modules) {
         boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
-        boolean isModuleDecl = toplevel.defs.nonEmpty() && toplevel.defs.head.hasTag(MODULEDEF);
+        boolean isModuleDecl = toplevel.getModuleDecl() != null;
         if (isModuleDecl) {
-            JCModuleDecl decl = (JCModuleDecl) toplevel.defs.head;
+            JCModuleDecl decl = toplevel.getModuleDecl();
             if (!isModuleInfo) {
                 log.error(decl.pos(), Errors.ModuleDeclSbInModuleInfoJava);
             }
@@ -352,8 +365,8 @@
                     if (locn != null) {
                         Name name = names.fromString(fileManager.inferModuleName(locn));
                         ModuleSymbol msym;
-                        if (tree.defs.head.hasTag(MODULEDEF)) {
-                            JCModuleDecl decl = (JCModuleDecl) tree.defs.head;
+                        JCModuleDecl decl = tree.getModuleDecl();
+                        if (decl != null) {
                             msym = decl.sym;
                             if (msym.name != name) {
                                 log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
@@ -449,17 +462,14 @@
     }
 
     private Location getModuleLocation(JCCompilationUnit tree) throws IOException {
-        switch (tree.defs.head.getTag()) {
-            case MODULEDEF:
-                return getModuleLocation(tree.sourcefile, null);
-
-            case PACKAGEDEF:
-                JCPackageDecl pkg = (JCPackageDecl) tree.defs.head;
-                return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid));
-
-            default:
-                // code in unnamed module
-                return null;
+        if (tree.getModuleDecl() != null) {
+            return getModuleLocation(tree.sourcefile, null);
+        } else if (tree.getPackage() != null) {
+            JCPackageDecl pkg = tree.getPackage();
+            return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid));
+        } else {
+            // code in unnamed module
+            return null;
         }
     }
 
@@ -535,6 +545,7 @@
                 String pack = binName.lastIndexOf('.') != (-1) ? binName.substring(0, binName.lastIndexOf('.')) : ""; //unnamed package????
                 if (seenPackages.add(pack)) {
                     ExportsDirective d = new ExportsDirective(syms.enterPackage(msym, names.fromString(pack)), null);
+                    //TODO: opens?
                     directives.add(d);
                     exports.add(d);
                 }
@@ -562,7 +573,7 @@
             if (ms == syms.unnamedModule || ms == msym)
                 continue;
             Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ?
-                    EnumSet.of(RequiresFlag.PUBLIC) : EnumSet.noneOf(RequiresFlag.class);
+                    EnumSet.of(RequiresFlag.TRANSITIVE) : EnumSet.noneOf(RequiresFlag.class);
             RequiresDirective d = new RequiresDirective(ms, flags);
             directives.add(d);
             requires.add(d);
@@ -585,9 +596,10 @@
                 ModuleVisitor v = new ModuleVisitor();
                 JavaFileObject prev = log.useSource(tree.sourcefile);
                 try {
-                    tree.defs.head.accept(v);
-                    checkCyclicDependencies((JCModuleDecl) tree.defs.head);
+                    JCModuleDecl moduleDecl = tree.getModuleDecl();
+                    moduleDecl.accept(v);
                     completeModule(msym);
+                    checkCyclicDependencies(moduleDecl);
                 } finally {
                     log.useSource(prev);
                     msym.flags_field &= ~UNATTRIBUTED;
@@ -605,17 +617,25 @@
     class ModuleVisitor extends JCTree.Visitor {
         private ModuleSymbol sym;
         private final Set<ModuleSymbol> allRequires = new HashSet<>();
-        private final Set<PackageSymbol> allExports = new HashSet<>();
+        private final Map<PackageSymbol,List<ExportsDirective>> allExports = new HashMap<>();
+        private final Map<PackageSymbol,List<OpensDirective>> allOpens = new HashMap<>();
 
         @Override
         public void visitModuleDef(JCModuleDecl tree) {
             sym = Assert.checkNonNull(tree.sym);
 
+            if (tree.getModuleType() == ModuleKind.OPEN) {
+                sym.flags.add(ModuleFlags.OPEN);
+            }
+            sym.flags_field |= (tree.mods.flags & Flags.DEPRECATED);
+
             sym.requires = List.nil();
             sym.exports = List.nil();
+            sym.opens = List.nil();
             tree.directives.forEach(t -> t.accept(this));
             sym.requires = sym.requires.reverse();
             sym.exports = sym.exports.reverse();
+            sym.opens = sym.opens.reverse();
             ensureJavaBase();
         }
 
@@ -629,8 +649,10 @@
             } else {
                 allRequires.add(msym);
                 Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class);
-                if (tree.isPublic)
-                    flags.add(RequiresFlag.PUBLIC);
+                if (tree.isTransitive)
+                    flags.add(RequiresFlag.TRANSITIVE);
+                if (tree.isStaticPhase)
+                    flags.add(RequiresFlag.STATIC_PHASE);
                 RequiresDirective d = new RequiresDirective(msym, flags);
                 tree.directive = d;
                 sym.requires = sym.requires.prepend(d);
@@ -642,31 +664,125 @@
             Name name = TreeInfo.fullName(tree.qualid);
             PackageSymbol packge = syms.enterPackage(sym, name);
             attr.setPackageSymbols(tree.qualid, packge);
-            if (!allExports.add(packge)) {
-                log.error(tree.qualid.pos(), Errors.DuplicateExports(packge));
+
+            if (tree.hasTag(Tag.OPENS) && sym.flags.contains(ModuleFlags.OPEN)) {
+                log.error(tree.pos(), Errors.NoOpensUnlessStrong);
+            }
+            List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil());
+            for (ExportsDirective d : exportsForPackage) {
+                reportExportsConflict(tree, packge);
             }
 
             List<ModuleSymbol> toModules = null;
             if (tree.moduleNames != null) {
-                Set<ModuleSymbol> to = new HashSet<>();
+                Set<ModuleSymbol> to = new LinkedHashSet<>();
                 for (JCExpression n: tree.moduleNames) {
                     ModuleSymbol msym = lookupModule(n);
                     if (msym.kind != MDL) {
                         log.error(n.pos(), Errors.ModuleNotFound(msym));
-                    } else if (!to.add(msym)) {
-                        log.error(n.pos(), Errors.DuplicateExports(msym));
+                    } else {
+                        for (ExportsDirective d : exportsForPackage) {
+                            checkDuplicateExportsToModule(n, msym, d);
+                        }
+                        if (!to.add(msym)) {
+                            reportExportsConflictToModule(n, msym);
+                        }
                     }
                 }
                 toModules = List.from(to);
             }
 
             if (toModules == null || !toModules.isEmpty()) {
-                ExportsDirective d = new ExportsDirective(packge, toModules);
-                tree.directive = d;
+                Set<ExportsFlag> flags = EnumSet.noneOf(ExportsFlag.class);
+                ExportsDirective d = new ExportsDirective(packge, toModules, flags);
                 sym.exports = sym.exports.prepend(d);
+                tree.directive = d;
+
+                allExports.put(packge, exportsForPackage.prepend(d));
             }
         }
 
+        private void reportExportsConflict(JCExports tree, PackageSymbol packge) {
+            log.error(tree.qualid.pos(), Errors.ConflictingExports(packge));
+        }
+
+        private void checkDuplicateExportsToModule(JCExpression name, ModuleSymbol msym,
+                ExportsDirective d) {
+            if (d.modules != null) {
+                for (ModuleSymbol other : d.modules) {
+                    if (msym == other) {
+                        reportExportsConflictToModule(name, msym);
+                    }
+                }
+            }
+        }
+
+        private void reportExportsConflictToModule(JCExpression name, ModuleSymbol msym) {
+            log.error(name.pos(), Errors.ConflictingExportsToModule(msym));
+        }
+
+        @Override
+        public void visitOpens(JCOpens tree) {
+            Name name = TreeInfo.fullName(tree.qualid);
+            PackageSymbol packge = syms.enterPackage(sym, name);
+            attr.setPackageSymbols(tree.qualid, packge);
+
+            if (sym.flags.contains(ModuleFlags.OPEN)) {
+                log.error(tree.pos(), Errors.NoOpensUnlessStrong);
+            }
+            List<OpensDirective> opensForPackage = allOpens.computeIfAbsent(packge, p -> List.nil());
+            for (OpensDirective d : opensForPackage) {
+                reportOpensConflict(tree, packge);
+            }
+
+            List<ModuleSymbol> toModules = null;
+            if (tree.moduleNames != null) {
+                Set<ModuleSymbol> to = new LinkedHashSet<>();
+                for (JCExpression n: tree.moduleNames) {
+                    ModuleSymbol msym = lookupModule(n);
+                    if (msym.kind != MDL) {
+                        log.error(n.pos(), Errors.ModuleNotFound(msym));
+                    } else {
+                        for (OpensDirective d : opensForPackage) {
+                            checkDuplicateOpensToModule(n, msym, d);
+                        }
+                        if (!to.add(msym)) {
+                            reportOpensConflictToModule(n, msym);
+                        }
+                    }
+                }
+                toModules = List.from(to);
+            }
+
+            if (toModules == null || !toModules.isEmpty()) {
+                Set<OpensFlag> flags = EnumSet.noneOf(OpensFlag.class);
+                OpensDirective d = new OpensDirective(packge, toModules, flags);
+                sym.opens = sym.opens.prepend(d);
+                tree.directive = d;
+
+                allOpens.put(packge, opensForPackage.prepend(d));
+            }
+        }
+
+        private void reportOpensConflict(JCOpens tree, PackageSymbol packge) {
+            log.error(tree.qualid.pos(), Errors.ConflictingOpens(packge));
+        }
+
+        private void checkDuplicateOpensToModule(JCExpression name, ModuleSymbol msym,
+                OpensDirective d) {
+            if (d.modules != null) {
+                for (ModuleSymbol other : d.modules) {
+                    if (msym == other) {
+                        reportOpensConflictToModule(name, msym);
+                    }
+                }
+            }
+        }
+
+        private void reportOpensConflictToModule(JCExpression name, ModuleSymbol msym) {
+            log.error(name.pos(), Errors.ConflictingOpensToModule(msym));
+        }
+
         @Override
         public void visitProvides(JCProvides tree) { }
 
@@ -706,10 +822,14 @@
             Env<AttrContext> env = typeEnvs.get(msym);
             UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
             JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
+            JCModuleDecl decl = env.toplevel.getModuleDecl();
+            DiagnosticPosition prevLintPos = deferredLintHandler.setPos(decl.pos());
+
             try {
-                env.toplevel.defs.head.accept(v);
+                decl.accept(v);
             } finally {
                 log.useSource(prev);
+                deferredLintHandler.setPos(prevLintPos);
             }
         };
     }
@@ -718,8 +838,8 @@
         private final ModuleSymbol msym;
         private final Env<AttrContext> env;
 
-        private final Set<Directive.UsesDirective> allUses = new HashSet<>();
-        private final Set<Directive.ProvidesDirective> allProvides = new HashSet<>();
+        private final Set<ClassSymbol> allUses = new HashSet<>();
+        private final Map<ClassSymbol, Set<ClassSymbol>> allProvides = new HashMap<>();
 
         public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) {
             this.msym = msym;
@@ -752,6 +872,15 @@
             msym.directives = msym.directives.prepend(tree.directive);
         }
 
+        @Override
+        public void visitOpens(JCOpens tree) {
+            if (tree.directive.packge.members().isEmpty() &&
+                ((tree.directive.packge.flags() & Flags.HAS_RESOURCE) == 0)) {
+                log.error(tree.qualid.pos(), Errors.PackageEmptyOrNotFound(tree.directive.packge));
+            }
+            msym.directives = msym.directives.prepend(tree.directive);
+        }
+
         MethodSymbol noArgsConstructor(ClassSymbol tsym) {
             for (Symbol sym : tsym.members().getSymbolsByName(names.init)) {
                 MethodSymbol mSym = (MethodSymbol)sym;
@@ -762,34 +891,61 @@
             return null;
         }
 
+        MethodSymbol factoryMethod(ClassSymbol tsym) {
+            for (Symbol sym : tsym.members().getSymbolsByName(names.provider, sym -> sym.kind == MTH)) {
+                MethodSymbol mSym = (MethodSymbol)sym;
+                if (mSym.isStatic() && (mSym.flags() & Flags.PUBLIC) != 0 && mSym.params().isEmpty()) {
+                    return mSym;
+                }
+            }
+            return null;
+        }
+
         Map<Directive.ProvidesDirective, JCProvides> directiveToTreeMap = new HashMap<>();
 
         @Override
         public void visitProvides(JCProvides tree) {
             Type st = attr.attribType(tree.serviceName, env, syms.objectType);
-            Type it = attr.attribType(tree.implName, env, syms.objectType);
             ClassSymbol service = (ClassSymbol) st.tsym;
-            ClassSymbol impl = (ClassSymbol) it.tsym;
-            if (!types.isSubtype(it, st)) {
-                log.error(tree.implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface);
-            }
-            if ((impl.flags() & ABSTRACT) != 0) {
-                log.error(tree.implName.pos(), Errors.ServiceImplementationIsAbstract(impl));
-            } else if (impl.isInner()) {
-                log.error(tree.implName.pos(), Errors.ServiceImplementationIsInner(impl));
-            } else {
-                MethodSymbol constr = noArgsConstructor(impl);
-                if (constr == null) {
-                    log.error(tree.implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl));
-                } else if ((constr.flags() & PUBLIC) == 0) {
-                    log.error(tree.implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl));
+            ListBuffer<ClassSymbol> impls = new ListBuffer<>();
+            for (JCExpression implName : tree.implNames) {
+                Type it = attr.attribType(implName, env, syms.objectType);
+                ClassSymbol impl = (ClassSymbol) it.tsym;
+                //find provider factory:
+                MethodSymbol factory = factoryMethod(impl);
+                if (factory != null) {
+                    Type returnType = factory.type.getReturnType();
+                    if (!types.isSubtype(returnType, st)) {
+                        log.error(implName.pos(), Errors.ServiceImplementationProviderReturnMustBeSubtypeOfServiceInterface);
+                    }
+                } else {
+                    if (!types.isSubtype(it, st)) {
+                        log.error(implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface);
+                    } else if ((impl.flags() & ABSTRACT) != 0) {
+                        log.error(implName.pos(), Errors.ServiceImplementationIsAbstract(impl));
+                    } else if (impl.isInner()) {
+                        log.error(implName.pos(), Errors.ServiceImplementationIsInner(impl));
+                    } else {
+                        MethodSymbol constr = noArgsConstructor(impl);
+                        if (constr == null) {
+                            log.error(implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl));
+                        } else if ((constr.flags() & PUBLIC) == 0) {
+                            log.error(implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl));
+                        }
+                    }
+                }
+                if (it.hasTag(CLASS)) {
+                    // For now, we just check the pair (service-type, impl-type) is unique
+                    // TODO, check only one provides per service type as well
+                    if (allProvides.computeIfAbsent(service, s -> new HashSet<>()).add(impl)) {
+                        impls.append(impl);
+                    } else {
+                        log.error(implName.pos(), Errors.DuplicateProvides(service, impl));
+                    }
                 }
             }
-            if (st.hasTag(CLASS) && it.hasTag(CLASS)) {
-                Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impl);
-                if (!allProvides.add(d)) {
-                    log.error(tree.pos(), Errors.DuplicateProvides(service, impl));
-                }
+            if (st.hasTag(CLASS) && !impls.isEmpty()) {
+                Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impls.toList());
                 msym.provides = msym.provides.prepend(d);
                 msym.directives = msym.directives.prepend(d);
                 directiveToTreeMap.put(d, tree);
@@ -799,6 +955,7 @@
         @Override
         public void visitRequires(JCRequires tree) {
             if (tree.directive != null) {
+                chk.checkDeprecated(tree.moduleName.pos(), msym, tree.directive.module);
                 msym.directives = msym.directives.prepend(tree.directive);
             }
         }
@@ -811,53 +968,58 @@
                 log.error(tree.qualid.pos(), Errors.ServiceDefinitionIsEnum(st.tsym));
             } else if (st.hasTag(CLASS)) {
                 ClassSymbol service = (ClassSymbol) st.tsym;
-                Directive.UsesDirective d = new Directive.UsesDirective(service);
-                if (!allUses.add(d)) {
+                if (allUses.add(service)) {
+                    Directive.UsesDirective d = new Directive.UsesDirective(service);
+                    msym.uses = msym.uses.prepend(d);
+                    msym.directives = msym.directives.prepend(d);
+                } else {
                     log.error(tree.pos(), Errors.DuplicateUses(service));
                 }
-                msym.uses = msym.uses.prepend(d);
-                msym.directives = msym.directives.prepend(d);
             }
         }
 
         private void checkForCorrectness() {
-            for (Directive.ProvidesDirective provides : allProvides) {
+            for (Directive.ProvidesDirective provides : msym.provides) {
                 JCProvides tree = directiveToTreeMap.get(provides);
-                /* The implementation must be defined in the same module as the provides directive
-                 * (else, error)
-                 */
-                PackageSymbol implementationDefiningPackage = provides.impl.packge();
-                if (implementationDefiningPackage.modle != msym) {
-                    log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle));
-                }
-
-                /* There is no inherent requirement that module that provides a service should actually
-                 * use it itself. However, it is a pointless declaration if the service package is not
-                 * exported and there is no uses for the service.
-                 */
-                PackageSymbol interfaceDeclaringPackage = provides.service.packge();
-                boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym;
-                boolean isInterfaceExportedFromAReadableModule =
-                        msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage;
-                if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) {
-                    // ok the interface is declared in this module. Let's check if it's exported
-                    boolean warn = true;
-                    for (ExportsDirective export : msym.exports) {
-                        if (interfaceDeclaringPackage == export.packge) {
-                            warn = false;
-                            break;
-                        }
+                for (ClassSymbol impl : provides.impls) {
+                    /* The implementation must be defined in the same module as the provides directive
+                     * (else, error)
+                     */
+                    PackageSymbol implementationDefiningPackage = impl.packge();
+                    if (implementationDefiningPackage.modle != msym) {
+                        // TODO: should use tree for the implentation name, not the entire provides tree
+                        // TODO: should improve error message to identify the implementation type
+                        log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle));
                     }
-                    if (warn) {
-                        for (UsesDirective uses : msym.uses) {
-                            if (provides.service == uses.service) {
+
+                    /* There is no inherent requirement that module that provides a service should actually
+                     * use it itself. However, it is a pointless declaration if the service package is not
+                     * exported and there is no uses for the service.
+                     */
+                    PackageSymbol interfaceDeclaringPackage = provides.service.packge();
+                    boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym;
+                    boolean isInterfaceExportedFromAReadableModule =
+                            msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage;
+                    if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) {
+                        // ok the interface is declared in this module. Let's check if it's exported
+                        boolean warn = true;
+                        for (ExportsDirective export : msym.exports) {
+                            if (interfaceDeclaringPackage == export.packge) {
                                 warn = false;
                                 break;
                             }
                         }
-                    }
-                    if (warn) {
-                        log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service));
+                        if (warn) {
+                            for (UsesDirective uses : msym.uses) {
+                                if (provides.service == uses.service) {
+                                    warn = false;
+                                    break;
+                                }
+                            }
+                        }
+                        if (warn) {
+                            log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service));
+                        }
                     }
                 }
             }
@@ -973,6 +1135,10 @@
         allModules = result;
     }
 
+    public boolean isInModuleGraph(ModuleSymbol msym) {
+        return allModules == null || allModules.contains(msym);
+    }
+
     private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
         List<ModuleSymbol> todo = List.nil();
 
@@ -1019,7 +1185,8 @@
                     return ;
                 }
                 ModuleSymbol msym = (ModuleSymbol) sym;
-                Set<ModuleSymbol> allModules = allModules();
+                Set<ModuleSymbol> allModules = new HashSet<>(allModules());
+                allModules.remove(syms.unnamedModule);
                 for (ModuleSymbol m : allModules) {
                     m.complete();
                 }
@@ -1033,7 +1200,7 @@
         };
     }
 
-    private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>();
+    private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresTransitiveCache = new HashMap<>();
 
     private void completeModule(ModuleSymbol msym) {
         if (inInitModules) {
@@ -1079,34 +1246,36 @@
         }
 
         Set<ModuleSymbol> readable = new LinkedHashSet<>();
-        Set<ModuleSymbol> requiresPublic = new HashSet<>();
+        Set<ModuleSymbol> requiresTransitive = new HashSet<>();
 
         for (RequiresDirective d : msym.requires) {
             d.module.complete();
             readable.add(d.module);
-            Set<ModuleSymbol> s = retrieveRequiresPublic(d.module);
+            Set<ModuleSymbol> s = retrieveRequiresTransitive(d.module);
             Assert.checkNonNull(s, () -> "no entry in cache for " + d.module);
             readable.addAll(s);
-            if (d.flags.contains(RequiresFlag.PUBLIC)) {
-                requiresPublic.add(d.module);
-                requiresPublic.addAll(s);
+            if (d.flags.contains(RequiresFlag.TRANSITIVE)) {
+                requiresTransitive.add(d.module);
+                requiresTransitive.addAll(s);
             }
         }
 
-        requiresPublicCache.put(msym, requiresPublic);
+        requiresTransitiveCache.put(msym, requiresTransitive);
         initVisiblePackages(msym, readable);
         for (ExportsDirective d: msym.exports) {
-            d.packge.modle = msym;
+            if (d.packge != null) {
+                d.packge.modle = msym;
+            }
         }
 
     }
 
-    private Set<ModuleSymbol> retrieveRequiresPublic(ModuleSymbol msym) {
-        Set<ModuleSymbol> requiresPublic = requiresPublicCache.get(msym);
+    private Set<ModuleSymbol> retrieveRequiresTransitive(ModuleSymbol msym) {
+        Set<ModuleSymbol> requiresTransitive = requiresTransitiveCache.get(msym);
 
-        if (requiresPublic == null) {
+        if (requiresTransitive == null) {
             //the module graph may contain cycles involving automatic modules or --add-reads edges
-            requiresPublic = new HashSet<>();
+            requiresTransitive = new HashSet<>();
 
             Set<ModuleSymbol> seen = new HashSet<>();
             List<ModuleSymbol> todo = List.of(msym);
@@ -1116,14 +1285,14 @@
                 todo = todo.tail;
                 if (!seen.add(current))
                     continue;
-                requiresPublic.add(current);
+                requiresTransitive.add(current);
                 current.complete();
                 Iterable<? extends RequiresDirective> requires;
                 if (current != syms.unnamedModule) {
                     Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym);
                     requires = current.requires;
                     for (RequiresDirective rd : requires) {
-                        if (rd.isPublic())
+                        if (rd.isTransitive())
                             todo = todo.prepend(rd.module);
                     }
                 } else {
@@ -1133,10 +1302,10 @@
                 }
             }
 
-            requiresPublic.remove(msym);
+            requiresTransitive.remove(msym);
         }
 
-        return requiresPublic;
+        return requiresTransitive;
     }
 
     private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
index c941de3..ff6bd71 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
@@ -160,8 +160,6 @@
         // if there remain any unimported toplevels (these must have
         // no classes at all), process their import statements as well.
         for (JCCompilationUnit tree : trees) {
-            if (tree.defs.nonEmpty() && tree.defs.head.hasTag(MODULEDEF))
-                continue;
             if (!tree.starImportScope.isFilled()) {
                 Env<AttrContext> topEnv = enter.topLevelEnv(tree);
                 finishImports(tree, () -> { completeClass.resolveImports(tree, topEnv); });
@@ -344,13 +342,22 @@
                     throw new FatalError(diags.fragment("fatal.err.no.java.lang"));
                 importAll(make.at(tree.pos()).Import(make.QualIdent(javaLang), false), javaLang, env);
 
+                JCModuleDecl decl = tree.getModuleDecl();
+
                 // Process the package def and all import clauses.
-                if (tree.getPackage() != null)
+                if (tree.getPackage() != null && decl == null)
                     checkClassPackageClash(tree.getPackage());
 
                 for (JCImport imp : tree.getImports()) {
                     doImport(imp);
                 }
+
+                if (decl != null) {
+                    //check @Deprecated:
+                    markDeprecated(decl.sym, decl.mods.annotations, env);
+                    // process module annotations
+                    annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle, null);
+                }
             } finally {
                 this.env = prevEnv;
                 chk.setLint(prevLint);
@@ -745,12 +752,7 @@
                 }
             }
 
-            // Annotations.
-            // In general, we cannot fully process annotations yet,  but we
-            // can attribute the annotation types and then check to see if the
-            // @Deprecated annotation is present.
-            attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
-            handleDeprecatedAnnotation(tree.mods.annotations, sym);
+            markDeprecated(sym, tree.mods.annotations, baseEnv);
 
             chk.checkNonCyclicDecl(tree);
         }
@@ -765,32 +767,6 @@
                 return superType;
             }
 
-            /**
-             * If a list of annotations contains a reference to java.lang.Deprecated,
-             * set the DEPRECATED flag.
-             * If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
-             **/
-            private void handleDeprecatedAnnotation(List<JCAnnotation> annotations, Symbol sym) {
-                for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
-                    JCAnnotation a = al.head;
-                    if (a.annotationType.type == syms.deprecatedType) {
-                        sym.flags_field |= Flags.DEPRECATED;
-                        a.args.stream()
-                                .filter(e -> e.hasTag(ASSIGN))
-                                .map(e -> (JCAssign) e)
-                                .filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval)
-                                .findFirst()
-                                .ifPresent(assign -> {
-                                    JCExpression rhs = TreeInfo.skipParens(assign.rhs);
-                                    if (rhs.hasTag(LITERAL)
-                                            && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
-                                        sym.flags_field |= DEPRECATED_REMOVAL;
-                                    }
-                                });
-                    }
-                }
-            }
-
         @Override
         public void complete(Symbol sym) throws CompletionFailure {
             Assert.check((topLevelPhase instanceof ImportsPhase) ||
@@ -1135,4 +1111,41 @@
         List<JCExpression> typeargs = typarams.nonEmpty() ? make.Types(typarams) : null;
         return make.Exec(make.Apply(typeargs, meth, make.Idents(params)));
     }
+
+    /**
+     * Mark sym deprecated if annotations contain @Deprecated annotation.
+     */
+    public void markDeprecated(Symbol sym, List<JCAnnotation> annotations, Env<AttrContext> env) {
+        // In general, we cannot fully process annotations yet,  but we
+        // can attribute the annotation types and then check to see if the
+        // @Deprecated annotation is present.
+        attr.attribAnnotationTypes(annotations, env);
+        handleDeprecatedAnnotations(annotations, sym);
+    }
+
+    /**
+     * If a list of annotations contains a reference to java.lang.Deprecated,
+     * set the DEPRECATED flag.
+     * If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
+     **/
+    private void handleDeprecatedAnnotations(List<JCAnnotation> annotations, Symbol sym) {
+        for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
+            JCAnnotation a = al.head;
+            if (a.annotationType.type == syms.deprecatedType) {
+                sym.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
+                a.args.stream()
+                        .filter(e -> e.hasTag(ASSIGN))
+                        .map(e -> (JCAssign) e)
+                        .filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval)
+                        .findFirst()
+                        .ifPresent(assign -> {
+                            JCExpression rhs = TreeInfo.skipParens(assign.rhs);
+                            if (rhs.hasTag(LITERAL)
+                                    && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
+                                sym.flags_field |= DEPRECATED_REMOVAL;
+                            }
+                        });
+            }
+        }
+    }
 }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
index bc3acd8..d28bd58 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
@@ -29,6 +29,7 @@
 import java.io.InputStream;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -128,7 +129,7 @@
 
     protected String classLoaderClass;
 
-    protected Locations locations;
+    protected final Locations locations;
 
     /**
      * A flag for clients to use to indicate that this file manager should
@@ -209,7 +210,10 @@
             addReadsMethod.invoke(thisModule, targetModule);
         } catch (NoSuchMethodException e) {
             // ignore
-        } catch (Exception e) {
+        } catch (IllegalAccessException
+                | IllegalArgumentException
+                | SecurityException
+                | InvocationTargetException e) {
             throw new Abort(e);
         }
         return targetLoader;
@@ -327,12 +331,12 @@
 
     @SuppressWarnings("cast")
     public CharBuffer decode(ByteBuffer inbuf, boolean ignoreEncodingErrors) {
-        String encodingName = getEncodingName();
+        String encName = getEncodingName();
         CharsetDecoder decoder;
         try {
-            decoder = getDecoder(encodingName, ignoreEncodingErrors);
+            decoder = getDecoder(encName, ignoreEncodingErrors);
         } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
-            log.error("unsupported.encoding", encodingName);
+            log.error("unsupported.encoding", encName);
             return (CharBuffer)CharBuffer.allocate(1).flip();
         }
 
@@ -368,7 +372,7 @@
                     unmappable.append(String.format("%02X", inbuf.get()));
                 }
 
-                String charsetName = charset == null ? encodingName : charset.name();
+                String charsetName = charset == null ? encName : charset.name();
 
                 log.error(dest.limit(),
                           Errors.IllegalCharForEncoding(unmappable.toString(), charsetName));
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
index 6e2ece4..5d87a3a 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
@@ -890,6 +890,8 @@
      * like UPGRADE_MODULE_PATH and MODULE_PATH.
      */
     private class ModulePathLocationHandler extends SimpleLocationHandler {
+        private Map<String, ModuleLocationHandler> pathModules;
+
         ModulePathLocationHandler(Location location, Option... options) {
             super(location, options);
         }
@@ -904,6 +906,12 @@
         }
 
         @Override
+        public Location getLocationForModule(String moduleName) {
+            initPathModules();
+            return pathModules.get(moduleName);
+        }
+
+        @Override
         Iterable<Set<Location>> listLocationsForModules() {
             if (searchPath == null)
                 return Collections.emptyList();
@@ -921,6 +929,23 @@
             super.setPaths(paths);
         }
 
+        private void initPathModules() {
+            if (pathModules != null) {
+                return;
+            }
+
+            pathModules = new LinkedHashMap<>();
+
+            for (Set<Location> set : listLocationsForModules()) {
+                for (Location locn : set) {
+                    if (locn instanceof ModuleLocationHandler) {
+                        ModuleLocationHandler h = (ModuleLocationHandler) locn;
+                        pathModules.put(h.moduleName, h);
+                    }
+                }
+            }
+        }
+
         private void checkValidModulePathEntry(Path p) {
             if (Files.isDirectory(p)) {
                 // either an exploded module or a directory of modules
@@ -1091,7 +1116,8 @@
                     }
 
                     // finally clean up the module name
-                    mn =  mn.replaceAll("[^A-Za-z0-9]", ".")  // replace non-alphanumeric
+                    mn =  mn.replaceAll("(\\.|\\d)*$", "")    // remove trailing version
+                            .replaceAll("[^A-Za-z0-9]", ".")  // replace non-alphanumeric
                             .replaceAll("(\\.)(\\1)+", ".")   // collapse repeating dots
                             .replaceAll("^\\.", "")           // drop leading dots
                             .replaceAll("\\.$", "");          // drop trailing dots
@@ -1157,7 +1183,6 @@
         private Map<String, Location> moduleLocations;
         private Map<Path, Location> pathLocations;
 
-
         ModuleSourcePathLocationHandler() {
             super(StandardLocation.MODULE_SOURCE_PATH,
                     Option.MODULE_SOURCE_PATH);
@@ -1396,7 +1421,8 @@
         }
 
         private void update(Path p) {
-            if (!isCurrentPlatform(p) && !Files.exists(p.resolve("jrt-fs.jar")) && !Files.exists(systemJavaHome.resolve("modules")))
+            if (!isCurrentPlatform(p) && !Files.exists(p.resolve("lib").resolve("jrt-fs.jar")) &&
+                    !Files.exists(systemJavaHome.resolve("modules")))
                 throw new IllegalArgumentException(p.toString());
             systemJavaHome = p;
             modules = null;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
index 62bfd05..b6d0580 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java
@@ -129,8 +129,11 @@
  * String Translation Routines
  ***********************************************************************/
 
-    /** Return internal representation of buf[offset..offset+len-1],
-     *  converting '/' to '.'.
+    /**
+     * Return internal representation of buf[offset..offset+len-1], converting '/' to '.'.
+     *
+     * Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
+     * which defines "internal name" to be the form using "/" instead of "."
      */
     public static byte[] internalize(byte[] buf, int offset, int len) {
         byte[] translated = new byte[len];
@@ -142,15 +145,21 @@
         return translated;
     }
 
-    /** Return internal representation of given name,
-     *  converting '/' to '.'.
+    /**
+     * Return internal representation of given name, converting '/' to '.'.
+     *
+     * Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
+     * which defines "internal name" to be the form using "/" instead of "."
      */
     public static byte[] internalize(Name name) {
         return internalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
     }
 
-    /** Return external representation of buf[offset..offset+len-1],
-     *  converting '.' to '/'.
+    /**
+     * Return external representation of buf[offset..offset+len-1], converting '.' to '/'.
+     *
+     * Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
+     * which defines "internal name" to be the form using "/" instead of "."
      */
     public static byte[] externalize(byte[] buf, int offset, int len) {
         byte[] translated = new byte[len];
@@ -162,8 +171,11 @@
         return translated;
     }
 
-    /** Return external representation of given name,
-     *  converting '/' to '.'.
+    /**
+     * Return external representation of given name, converting '/' to '.'.
+     *
+     * Note: the naming is the inverse of that used by JVMS 4.2 The Internal Form Of Names,
+     * which defines "internal name" to be the form using "/" instead of "."
      */
     public static byte[] externalize(Name name) {
         return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
index 1416d2b..fc92dea 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
@@ -62,7 +62,9 @@
 
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
+
 import com.sun.tools.javac.code.Scope.LookupKind;
+
 import static com.sun.tools.javac.code.TypeTag.ARRAY;
 import static com.sun.tools.javac.code.TypeTag.CLASS;
 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
@@ -159,6 +161,9 @@
      */
     protected ModuleSymbol currentModule = null;
 
+    // FIXME: temporary compatibility code
+    private boolean readNewModuleAttribute;
+
     /** The buffer containing the currently read class file.
      */
     byte[] buf = new byte[INITIAL_BUFFER_SIZE];
@@ -584,6 +589,53 @@
         throw badClassFile("bad.module-info.name");
     }
 
+    /** Read the name of a module.
+     * The name is stored in a CONSTANT_Utf8 entry, in
+     * JVMS 4.2 internal form (with '/' instead of '.')
+     */
+    Name readModuleName(int i) {
+        Name name = readName(i);
+        // FIXME: temporary compatibility code
+        if (readNewModuleAttribute) {
+            return names.fromUtf(internalize(name));
+        } else {
+            return name;
+        }
+    }
+
+    /** Read module_flags.
+     */
+    Set<ModuleFlags> readModuleFlags(int flags) {
+        Set<ModuleFlags> set = EnumSet.noneOf(ModuleFlags.class);
+        for (ModuleFlags f : ModuleFlags.values()) {
+            if ((flags & f.value) != 0)
+                set.add(f);
+        }
+        return set;
+    }
+
+    /** Read exports_flags.
+     */
+    Set<ExportsFlag> readExportsFlags(int flags) {
+        Set<ExportsFlag> set = EnumSet.noneOf(ExportsFlag.class);
+        for (ExportsFlag f: ExportsFlag.values()) {
+            if ((flags & f.value) != 0)
+                set.add(f);
+        }
+        return set;
+    }
+
+    /** Read opens_flags.
+     */
+    Set<OpensFlag> readOpensFlags(int flags) {
+        Set<OpensFlag> set = EnumSet.noneOf(OpensFlag.class);
+        for (OpensFlag f: OpensFlag.values()) {
+            if ((flags & f.value) != 0)
+                set.add(f);
+        }
+        return set;
+    }
+
     /** Read requires_flags.
      */
     Set<RequiresFlag> readRequiresFlags(int flags) {
@@ -996,7 +1048,9 @@
 
             new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
                 protected void read(Symbol sym, int attrLen) {
-                    sym.flags_field |= DEPRECATED;
+                    Symbol s = sym.owner.kind == MDL ? sym.owner : sym;
+
+                    s.flags_field |= DEPRECATED;
                 }
             },
 
@@ -1228,11 +1282,20 @@
                         ModuleSymbol msym = (ModuleSymbol) sym.owner;
                         ListBuffer<Directive> directives = new ListBuffer<>();
 
+                        // FIXME: temporary compatibility code
+                        if (readNewModuleAttribute) {
+                            Name moduleName = readModuleName(nextChar());
+                            if (currentModule.name != moduleName) {
+                                throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
+                            }
+                        }
+
+                        msym.flags.addAll(readModuleFlags(nextChar()));
+
                         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
                         int nrequires = nextChar();
                         for (int i = 0; i < nrequires; i++) {
-                            Name name = readName(nextChar());
-                            ModuleSymbol rsym = syms.enterModule(name);
+                            ModuleSymbol rsym = syms.enterModule(readModuleName(nextChar()));
                             Set<RequiresFlag> flags = readRequiresFlags(nextChar());
                             requires.add(new RequiresDirective(rsym, flags));
                         }
@@ -1244,6 +1307,7 @@
                         for (int i = 0; i < nexports; i++) {
                             Name n = readName(nextChar());
                             PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+                            Set<ExportsFlag> flags = readExportsFlags(nextChar());
                             int nto = nextChar();
                             List<ModuleSymbol> to;
                             if (nto == 0) {
@@ -1251,13 +1315,36 @@
                             } else {
                                 ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
                                 for (int t = 0; t < nto; t++)
-                                    lb.append(syms.enterModule(readName(nextChar())));
+                                    lb.append(syms.enterModule(readModuleName(nextChar())));
                                 to = lb.toList();
                             }
-                            exports.add(new ExportsDirective(p, to));
+                            exports.add(new ExportsDirective(p, to, flags));
                         }
                         msym.exports = exports.toList();
                         directives.addAll(msym.exports);
+                        ListBuffer<OpensDirective> opens = new ListBuffer<>();
+                        int nopens = nextChar();
+                        if (nopens != 0 && msym.flags.contains(ModuleFlags.OPEN)) {
+                            throw badClassFile("module.non.zero.opens", currentModule.name);
+                        }
+                        for (int i = 0; i < nopens; i++) {
+                            Name n = readName(nextChar());
+                            PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+                            Set<OpensFlag> flags = readOpensFlags(nextChar());
+                            int nto = nextChar();
+                            List<ModuleSymbol> to;
+                            if (nto == 0) {
+                                to = null;
+                            } else {
+                                ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
+                                for (int t = 0; t < nto; t++)
+                                    lb.append(syms.enterModule(readModuleName(nextChar())));
+                                to = lb.toList();
+                            }
+                            opens.add(new OpensDirective(p, to, flags));
+                        }
+                        msym.opens = opens.toList();
+                        directives.addAll(msym.opens);
 
                         msym.directives = directives.toList();
 
@@ -1271,17 +1358,21 @@
 
                         ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
                         int nprovides = nextChar();
-                        for (int i = 0; i < nprovides; i++) {
+                        for (int p = 0; p < nprovides; p++) {
                             Name srvc = readClassName(nextChar());
-                            Name impl = readClassName(nextChar());
-                            provides.add(new InterimProvidesDirective(srvc, impl));
+                            int nimpls = nextChar();
+                            ListBuffer<Name> impls = new ListBuffer<>();
+                            for (int i = 0; i < nimpls; i++) {
+                                impls.append(readClassName(nextChar()));
+                            provides.add(new InterimProvidesDirective(srvc, impls.toList()));
+                            }
                         }
                         interimProvides = provides.toList();
                     }
                 }
             },
 
-            new AttributeReader(names.Version, V53, CLASS_ATTRIBUTE) {
+            new AttributeReader(names.ModuleVersion, V53, CLASS_ATTRIBUTE) {
                 @Override
                 protected boolean accepts(AttributeKind kind) {
                     return super.accepts(kind) && allowModules;
@@ -1480,7 +1571,7 @@
                     } else if (proxy.type.tsym == syms.repeatableType.tsym) {
                         repeatable = proxy;
                     } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
-                        sym.flags_field |= DEPRECATED;
+                        sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
                         for (Pair<Name, Attribute> v : proxy.values) {
                             if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) {
                                 Attribute.Constant c = (Attribute.Constant) v.snd;
@@ -1547,7 +1638,7 @@
         // support preliminary jsr175-format class files
         if (buf[poolIdx[i]] == CONSTANT_Class)
             return readClassSymbol(i).type;
-        return readType(i);
+        return readTypeToProxy(i);
     }
     Type readEnumType(int i) {
         // support preliminary jsr175-format class files
@@ -1555,11 +1646,25 @@
         int length = getChar(index + 1);
         if (buf[index + length + 2] != ';')
             return enterClass(readName(i)).type;
-        return readType(i);
+        return readTypeToProxy(i);
+    }
+    Type readTypeToProxy(int i) {
+        if (currentModule.module_info == currentOwner) {
+            int index = poolIdx[i];
+            return new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
+        } else {
+            return readType(i);
+        }
     }
 
     CompoundAnnotationProxy readCompoundAnnotation() {
-        Type t = readTypeOrClassSymbol(nextChar());
+        Type t;
+        if (currentModule.module_info == currentOwner) {
+            int index = poolIdx[nextChar()];
+            t = new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
+        } else {
+            t = readTypeOrClassSymbol(nextChar());
+        }
         int numFields = nextChar();
         ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
         for (int i=0; i<numFields; i++) {
@@ -1800,7 +1905,7 @@
         case 'e':
             return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
         case 'c':
-            return new Attribute.Class(types, readTypeOrClassSymbol(nextChar()));
+            return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
         case '[': {
             int n = nextChar();
             ListBuffer<Attribute> l = new ListBuffer<>();
@@ -1817,6 +1922,7 @@
 
     interface ProxyVisitor extends Attribute.Visitor {
         void visitEnumAttributeProxy(EnumAttributeProxy proxy);
+        void visitClassAttributeProxy(ClassAttributeProxy proxy);
         void visitArrayAttributeProxy(ArrayAttributeProxy proxy);
         void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy);
     }
@@ -1836,6 +1942,19 @@
         }
     }
 
+    static class ClassAttributeProxy extends Attribute {
+        Type classType;
+        public ClassAttributeProxy(Type classType) {
+            super(null);
+            this.classType = classType;
+        }
+        public void accept(Visitor v) { ((ProxyVisitor)v).visitClassAttributeProxy(this); }
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public String toString() {
+            return "/*proxy class*/" + classType + ".class";
+        }
+    }
+
     static class ArrayAttributeProxy extends Attribute {
         List<Attribute> values;
         ArrayAttributeProxy(List<Attribute> values) {
@@ -1909,14 +2028,15 @@
         }
 
         Attribute.Compound deproxyCompound(CompoundAnnotationProxy a) {
+            Type annotationType = resolvePossibleProxyType(a.type);
             ListBuffer<Pair<Symbol.MethodSymbol,Attribute>> buf = new ListBuffer<>();
             for (List<Pair<Name,Attribute>> l = a.values;
                  l.nonEmpty();
                  l = l.tail) {
-                MethodSymbol meth = findAccessMethod(a.type, l.head.fst);
+                MethodSymbol meth = findAccessMethod(annotationType, l.head.fst);
                 buf.append(new Pair<>(meth, deproxy(meth.type.getReturnType(), l.head.snd)));
             }
-            return new Attribute.Compound(a.type, buf.toList());
+            return new Attribute.Compound(annotationType, buf.toList());
         }
 
         MethodSymbol findAccessMethod(Type container, Name name) {
@@ -2000,7 +2120,8 @@
 
         public void visitEnumAttributeProxy(EnumAttributeProxy proxy) {
             // type.tsym.flatName() should == proxy.enumFlatName
-            TypeSymbol enumTypeSym = proxy.enumType.tsym;
+            Type enumType = resolvePossibleProxyType(proxy.enumType);
+            TypeSymbol enumTypeSym = enumType.tsym;
             VarSymbol enumerator = null;
             CompletionFailure failure = null;
             try {
@@ -2030,6 +2151,12 @@
             }
         }
 
+        @Override
+        public void visitClassAttributeProxy(ClassAttributeProxy proxy) {
+            Type classType = resolvePossibleProxyType(proxy.classType);
+            result = new Attribute.Class(types, classType);
+        }
+
         public void visitArrayAttributeProxy(ArrayAttributeProxy proxy) {
             int length = proxy.values.length();
             Attribute[] ats = new Attribute[length];
@@ -2044,6 +2171,21 @@
         public void visitCompoundAnnotationProxy(CompoundAnnotationProxy proxy) {
             result = deproxyCompound(proxy);
         }
+
+        Type resolvePossibleProxyType(Type t) {
+            if (t instanceof ProxyType) {
+                Assert.check(requestingOwner.owner.kind == MDL);
+                ModuleSymbol prevCurrentModule = currentModule;
+                currentModule = (ModuleSymbol) requestingOwner.owner;
+                try {
+                    return ((ProxyType) t).resolve();
+                } finally {
+                    currentModule = prevCurrentModule;
+                }
+            } else {
+                return t;
+            }
+        }
     }
 
     class AnnotationDefaultCompleter extends AnnotationDeproxy implements Runnable {
@@ -2086,7 +2228,11 @@
         AnnotationCompleter(Symbol sym, List<CompoundAnnotationProxy> l) {
             super(currentOwner.kind == MTH
                     ? currentOwner.enclClass() : (ClassSymbol)currentOwner);
-            this.sym = sym;
+            if (sym.kind == TYP && sym.owner.kind == MDL) {
+                this.sym = sym.owner;
+            } else {
+                this.sym = sym;
+            }
             this.l = l;
             this.classFile = currentClassFile;
         }
@@ -2097,6 +2243,18 @@
             try {
                 currentClassFile = classFile;
                 List<Attribute.Compound> newList = deproxyCompoundList(l);
+                for (Attribute.Compound attr : newList) {
+                    if (attr.type.tsym == syms.deprecatedType.tsym) {
+                        sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
+                        Attribute forRemoval = attr.member(names.forRemoval);
+                        if (forRemoval instanceof Attribute.Constant) {
+                            Attribute.Constant c = (Attribute.Constant) forRemoval;
+                            if (c.type == syms.booleanType && ((Integer) c.value) != 0) {
+                                sym.flags_field |= DEPRECATED_REMOVAL;
+                            }
+                        }
+                    }
+                }
                 if (sym.annotationsPendingCompletion()) {
                     sym.setDeclarationAttributes(newList);
                 } else {
@@ -2407,15 +2565,22 @@
             }
         } else {
             c.flags_field = flags;
-            Name modInfoName = readModuleInfoName(nextChar());
             currentModule = (ModuleSymbol) c.owner;
-            if (currentModule.name.append('.', names.module_info) != modInfoName) {
-                //strip trailing .module-info, if exists:
-                int modInfoStart = modInfoName.length() - names.module_info.length();
-                modInfoName = modInfoName.subName(modInfoStart, modInfoName.length()) == names.module_info &&
-                              modInfoName.charAt(modInfoStart - 1) == '.' ?
-                                  modInfoName.subName(0, modInfoStart - 1) : modInfoName;
-                throw badClassFile("module.name.mismatch", modInfoName, currentModule.name);
+            int this_class = nextChar();
+            // FIXME: temporary compatibility code
+            if (this_class == 0) {
+                readNewModuleAttribute = true;
+            } else {
+                Name modInfoName = readModuleInfoName(this_class);
+                if (currentModule.name.append('.', names.module_info) != modInfoName) {
+                    //strip trailing .module-info, if exists:
+                    int modInfoStart = modInfoName.length() - names.module_info.length();
+                    modInfoName = modInfoName.subName(modInfoStart, modInfoName.length()) == names.module_info &&
+                                  modInfoName.charAt(modInfoStart - 1) == '.' ?
+                                      modInfoName.subName(0, modInfoStart - 1) : modInfoName;
+                    throw badClassFile("module.name.mismatch", modInfoName, currentModule.name);
+                }
+                readNewModuleAttribute = false;
             }
         }
 
@@ -2500,7 +2665,7 @@
 
         minorVersion = nextChar();
         majorVersion = nextChar();
-        int maxMajor = Version.MAX().major;
+        int maxMajor = 53; // Version.MAX().major;  //******* TEMPORARY *******
         int maxMinor = Version.MAX().minor;
         if (majorVersion > maxMajor ||
             majorVersion * 1000 + minorVersion <
@@ -2542,6 +2707,8 @@
                 List<Type> found = foundTypeVariables;
                 missingTypeVariables = List.nil();
                 foundTypeVariables = List.nil();
+                interimUses = List.nil();
+                interimProvides = List.nil();
                 filling = false;
                 ClassType ct = (ClassType)currentOwner.type;
                 ct.supertype_field =
@@ -2808,6 +2975,36 @@
         }
     }
 
+    private class ProxyType extends Type {
+
+        private final byte[] content;
+
+        public ProxyType(byte[] content) {
+            super(syms.noSymbol, TypeMetadata.EMPTY);
+            this.content = content;
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return TypeTag.NONE;
+        }
+
+        @Override
+        public Type cloneWithMetadata(TypeMetadata metadata) {
+            throw new UnsupportedOperationException();
+        }
+
+        public Type resolve() {
+            return sigToType(content, 0, content.length);
+        }
+
+        @Override @DefinedBy(Api.LANGUAGE_MODEL)
+        public String toString() {
+            return "<ProxyType>";
+        }
+
+    }
+
     private static final class InterimUsesDirective {
         public final Name service;
 
@@ -2819,11 +3016,11 @@
 
     private static final class InterimProvidesDirective {
         public final Name service;
-        public final Name impl;
+        public final List<Name> impls;
 
-        public InterimProvidesDirective(Name service, Name impl) {
+        public InterimProvidesDirective(Name service, List<Name> impls) {
             this.service = service;
-            this.impl = impl;
+            this.impls = impls;
         }
 
     }
@@ -2852,8 +3049,12 @@
             currentModule.uses = uses.toList();
             ListBuffer<ProvidesDirective> provides = new ListBuffer<>();
             for (InterimProvidesDirective interim : interimProvidesCopy) {
+                ListBuffer<ClassSymbol> impls = new ListBuffer<>();
+                for (Name impl : interim.impls) {
+                    impls.append(syms.enterClass(currentModule, impl));
+                }
                 ProvidesDirective d = new ProvidesDirective(syms.enterClass(currentModule, interim.service),
-                                                            syms.enterClass(currentModule, interim.impl));
+                                                            impls.toList());
                 provides.add(d);
                 directives.add(d);
             }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
index bfc72fc..88d9130 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
@@ -30,6 +30,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 
 import javax.tools.JavaFileManager;
 import javax.tools.FileObject;
@@ -952,6 +953,10 @@
         ModuleSymbol m = (ModuleSymbol) c.owner;
 
         int alenIdx = writeAttr(names.Module);
+
+        databuf.appendChar(pool.put(names.fromUtf(externalize(m.name))));
+        databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
+
         ListBuffer<RequiresDirective> requires = new ListBuffer<>();
         for (RequiresDirective r: m.requires) {
             if (!r.flags.contains(RequiresFlag.EXTRA))
@@ -959,7 +964,7 @@
         }
         databuf.appendChar(requires.size());
         for (RequiresDirective r: requires) {
-            databuf.appendChar(pool.put(r.module.name));
+            databuf.appendChar(pool.put(names.fromUtf(externalize(r.module.name))));
             databuf.appendChar(RequiresFlag.value(r.flags));
         }
 
@@ -967,12 +972,29 @@
         databuf.appendChar(exports.size());
         for (ExportsDirective e: exports) {
             databuf.appendChar(pool.put(names.fromUtf(externalize(e.packge.flatName()))));
+            databuf.appendChar(ExportsFlag.value(e.flags));
             if (e.modules == null) {
                 databuf.appendChar(0);
             } else {
                 databuf.appendChar(e.modules.size());
-                for (ModuleSymbol msym: e.modules)
-                    databuf.appendChar(pool.put(msym.name));
+                for (ModuleSymbol msym: e.modules) {
+                    databuf.appendChar(pool.put(names.fromUtf(externalize(msym.name))));
+                }
+            }
+        }
+
+        List<OpensDirective> opens = m.opens;
+        databuf.appendChar(opens.size());
+        for (OpensDirective o: opens) {
+            databuf.appendChar(pool.put(names.fromUtf(externalize(o.packge.flatName()))));
+            databuf.appendChar(OpensFlag.value(o.flags));
+            if (o.modules == null) {
+                databuf.appendChar(0);
+            } else {
+                databuf.appendChar(o.modules.size());
+                for (ModuleSymbol msym: o.modules) {
+                    databuf.appendChar(pool.put(names.fromUtf(externalize(msym.name))));
+                }
             }
         }
 
@@ -982,12 +1004,19 @@
             databuf.appendChar(pool.put(s.service));
         }
 
-        List<ProvidesDirective> services = m.provides;
-        databuf.appendChar(services.size());
-        for (ProvidesDirective s: services) {
-            databuf.appendChar(pool.put(s.service));
-            databuf.appendChar(pool.put(s.impl));
+        // temporary fix to merge repeated provides clause for same service;
+        // eventually this should be disallowed when analyzing the module,
+        // so that each service type only appears once.
+        Map<ClassSymbol, Set<ClassSymbol>> mergedProvides = new LinkedHashMap<>();
+        for (ProvidesDirective p : m.provides) {
+            mergedProvides.computeIfAbsent(p.service, s -> new LinkedHashSet<>()).addAll(p.impls);
         }
+        databuf.appendChar(mergedProvides.size());
+        mergedProvides.forEach((srvc, impls) -> {
+            databuf.appendChar(pool.put(srvc));
+            databuf.appendChar(impls.size());
+            impls.forEach(impl -> databuf.appendChar(pool.put(impl)));
+        });
 
         endAttr(alenIdx);
         return 1;
@@ -1688,7 +1717,11 @@
         }
         databuf.appendChar(flags);
 
-        databuf.appendChar(pool.put(c));
+        if (c.owner.kind == MDL) {
+            databuf.appendChar(0);
+        } else {
+            databuf.appendChar(pool.put(c));
+        }
         databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0);
         databuf.appendChar(interfaces.length());
         for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
@@ -1766,12 +1799,20 @@
         acount += writeEnclosingMethodAttribute(c);
         if (c.owner.kind == MDL) {
             acount += writeModuleAttribute(c);
+            acount += writeFlagAttrs(c.owner.flags());
         }
         acount += writeExtraClassAttributes(c);
 
         poolbuf.appendInt(JAVA_MAGIC);
-        poolbuf.appendChar(target.minorVersion);
-        poolbuf.appendChar(target.majorVersion);
+
+        if (c.owner.kind == MDL) {
+            // temporarily overide to force use of v53 for module-info.class
+            poolbuf.appendChar(0);
+            poolbuf.appendChar(53);
+        } else {
+            poolbuf.appendChar(target.minorVersion);
+            poolbuf.appendChar(target.majorVersion);
+        }
 
         writePool(c.pool);
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java
index e8f4bb2..bdb1620 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java
@@ -31,8 +31,6 @@
 
 import javax.tools.JavaFileObject;
 
-import com.sun.tools.javac.jvm.ClassFile;
-
 import static com.sun.tools.javac.jvm.ClassFile.*;
 
 
@@ -93,11 +91,44 @@
 
         int minorVersion = nextChar();
         int majorVersion = nextChar();
+        if (majorVersion < 53)
+            throw new BadClassFile("bad major version number for module: " + majorVersion);
 
         indexPool();
 
-        int accessflags = nextChar();
-        return readModuleInfoName(nextChar());
+        int access_flags = nextChar();
+        if (access_flags != 0x8000)
+            throw new BadClassFile("invalid access flags for module: 0x" + Integer.toHexString(access_flags));
+
+        // FIXME: temporary compatibility code
+        int this_class = nextChar();
+        if (this_class == 0) {
+            // new form
+            checkZero(nextChar(), "super_class");
+            checkZero(nextChar(), "interface_count");
+            checkZero(nextChar(), "fields_count");
+            checkZero(nextChar(), "methods_count");
+            int attributes_count = nextChar();
+            for (int i = 0; i < attributes_count; i++) {
+                int attr_name = nextChar();
+                int attr_length = nextInt();
+                if (getUtf8Value(attr_name, false).equals("Module") && attr_length > 2) {
+                    return getUtf8Value(nextChar(), true);
+                } else {
+                    // skip over unknown attributes
+                    bp += attr_length;
+                }
+            }
+            throw new BadClassFile("no Module attribute");
+        } else {
+            // old form
+            return readModuleInfoName(this_class);
+        }
+    }
+
+    void checkZero(int count, String name) throws BadClassFile {
+        if (count != 0)
+            throw new BadClassFile("invalid " + name + " for module: " + count);
     }
 
     /** Extract a character at position bp from buf.
@@ -166,6 +197,20 @@
         }
     }
 
+    String getUtf8Value(int index, boolean internalize) throws BadClassFile {
+        int utf8Index = poolIdx[index];
+        if (buf[utf8Index] == CONSTANT_Utf8) {
+            int len = getChar(utf8Index + 1);
+            int start = utf8Index + 3;
+            if (internalize) {
+                return new String(ClassFile.internalize(buf, start, len));
+            } else {
+                return new String(buf, start, len);
+            }
+        }
+        throw new BadClassFile("bad name at index " + index);
+    }
+
     /** Read the class name of a module-info.class file.
      * The name is stored in a CONSTANT_Class entry, where the
      * class name is of the form module-name/module-info.
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
index 007eeac..328b1fb 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
@@ -605,8 +605,9 @@
             log.error(Errors.ProcessorpathNoProcessormodulepath);
         }
 
-        if (obsoleteOptionFound)
+        if (obsoleteOptionFound && lintOptions) {
             log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
+        }
 
         SourceVersion sv = Source.toSourceVersion(source);
         validateAddExports(sv);
@@ -614,6 +615,10 @@
         validateAddReads(sv);
         validateLimitModules(sv);
 
+        if (lintOptions && options.isSet(Option.ADD_OPENS)) {
+            log.warning(LintCategory.OPTIONS, Warnings.AddopensIgnored);
+        }
+
         return !errors && (log.nerrors == 0);
     }
 
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
index 27edb7b0..9480ca0 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
@@ -561,6 +561,8 @@
         }
     },
 
+    ADD_OPENS("--add-opens", null, null, HIDDEN, BASIC),
+
     ADD_READS("--add-reads", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) {
         @Override
         public void process(OptionHelper helper, String option, String arg) throws InvalidValueException {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
index 450f949..eb43d8f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java
@@ -375,7 +375,8 @@
     @DefinedBy(Api.LANGUAGE_MODEL)
     public boolean isDeprecated(Element e) {
         Symbol sym = cast(Symbol.class, e);
-        return (sym.flags() & Flags.DEPRECATED) != 0;
+        sym.complete();
+        return sym.isDeprecated();
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index e0f9369..7e786ce 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -29,6 +29,7 @@
 import java.util.stream.Collectors;
 
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
+import com.sun.source.tree.ModuleTree.ModuleKind;
 
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.parser.Tokens.*;
@@ -51,7 +52,6 @@
 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
-import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
 
 /** The parser maps a token sequence into an abstract syntax
  *  tree. It operates by recursive descent, with code derived
@@ -3105,65 +3105,78 @@
         Token firstToken = token;
         JCModifiers mods = null;
         boolean consumedToplevelDoc = false;
+        boolean seenImport = false;
+        boolean seenPackage = false;
         ListBuffer<JCTree> defs = new ListBuffer<>();
+        if (token.kind == MONKEYS_AT)
+            mods = modifiersOpt();
 
-        if (token.kind == IDENTIFIER && token.name() == names.module) {
-            defs.append(moduleDecl(token.comment(CommentStyle.JAVADOC)));
+        if (token.kind == PACKAGE) {
+            int packagePos = token.pos;
+            List<JCAnnotation> annotations = List.nil();
+            seenPackage = true;
+            if (mods != null) {
+                checkNoMods(mods.flags);
+                annotations = mods.annotations;
+                mods = null;
+            }
+            nextToken();
+            JCExpression pid = qualident(false);
+            accept(SEMI);
+            JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
+            attach(pd, firstToken.comment(CommentStyle.JAVADOC));
             consumedToplevelDoc = true;
-        } else {
-            boolean seenImport = false;
-            boolean seenPackage = false;
-            if (token.kind == MONKEYS_AT)
-                mods = modifiersOpt();
-
-            if (token.kind == PACKAGE) {
-                int packagePos = token.pos;
-                List<JCAnnotation> annotations = List.nil();
-                seenPackage = true;
-                if (mods != null) {
-                    checkNoMods(mods.flags);
-                    annotations = mods.annotations;
-                    mods = null;
-                }
-                nextToken();
-                JCExpression pid = qualident(false);
-                accept(SEMI);
-                JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid);
-                attach(pd, firstToken.comment(CommentStyle.JAVADOC));
-                consumedToplevelDoc = true;
-                storeEnd(pd, token.pos);
-                defs.append(pd);
-            }
-            boolean checkForImports = true;
-            boolean firstTypeDecl = true;
-            while (token.kind != EOF) {
-                if (token.pos <= endPosTable.errorEndPos) {
-                    // error recovery
-                    skip(checkForImports, false, false, false);
-                    if (token.kind == EOF)
-                        break;
-                }
-                if (checkForImports && mods == null && token.kind == IMPORT) {
-                    seenImport = true;
-                    defs.append(importDeclaration());
-                } else {
-                    Comment docComment = token.comment(CommentStyle.JAVADOC);
-                    if (firstTypeDecl && !seenImport && !seenPackage) {
-                        docComment = firstToken.comment(CommentStyle.JAVADOC);
-                        consumedToplevelDoc = true;
-                    }
-                    JCTree def = typeDeclaration(mods, docComment);
-                    if (def instanceof JCExpressionStatement)
-                        def = ((JCExpressionStatement)def).expr;
-                    defs.append(def);
-                    if (def instanceof JCClassDecl)
-                        checkForImports = false;
-                    mods = null;
-                    firstTypeDecl = false;
-                }
-            }
+            storeEnd(pd, token.pos);
+            defs.append(pd);
         }
 
+        boolean checkForImports = true;
+        boolean firstTypeDecl = true;
+        while (token.kind != EOF) {
+            if (token.pos <= endPosTable.errorEndPos) {
+                // error recovery
+                skip(checkForImports, false, false, false);
+                if (token.kind == EOF)
+                    break;
+            }
+            if (checkForImports && mods == null && token.kind == IMPORT) {
+                seenImport = true;
+                defs.append(importDeclaration());
+            } else {
+                Comment docComment = token.comment(CommentStyle.JAVADOC);
+                if (firstTypeDecl && !seenImport && !seenPackage) {
+                    docComment = firstToken.comment(CommentStyle.JAVADOC);
+                    consumedToplevelDoc = true;
+                }
+                if (mods != null || token.kind != SEMI)
+                    mods = modifiersOpt(mods);
+                if (firstTypeDecl && token.kind == IDENTIFIER) {
+                    ModuleKind kind = ModuleKind.STRONG;
+                    if (token.name() == names.open) {
+                        kind = ModuleKind.OPEN;
+                        nextToken();
+                    }
+                    if (token.kind == IDENTIFIER && token.name() == names.module) {
+                        if (mods != null) {
+                            checkNoMods(mods.flags & ~Flags.DEPRECATED);
+                        }
+                        defs.append(moduleDecl(mods, kind, docComment));
+                        consumedToplevelDoc = true;
+                        break;
+                    } else if (kind != ModuleKind.STRONG) {
+                        reportSyntaxError(token.pos, "expected.module");
+                    }
+                }
+                JCTree def = typeDeclaration(mods, docComment);
+                if (def instanceof JCExpressionStatement)
+                    def = ((JCExpressionStatement)def).expr;
+                defs.append(def);
+                if (def instanceof JCClassDecl)
+                    checkForImports = false;
+                mods = null;
+                firstTypeDecl = false;
+            }
+        }
         JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(defs.toList());
         if (!consumedToplevelDoc)
             attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
@@ -3178,7 +3191,7 @@
         return toplevel;
     }
 
-    JCModuleDecl moduleDecl(Comment dc) {
+    JCModuleDecl moduleDecl(JCModifiers mods, ModuleKind kind, Comment dc) {
         int pos = token.pos;
         if (!allowModules) {
             log.error(pos, Errors.ModulesNotSupportedInSource(source.name));
@@ -3194,7 +3207,7 @@
         accept(RBRACE);
         accept(EOF);
 
-        JCModuleDecl result = toP(F.at(pos).ModuleDef(name, directives));
+        JCModuleDecl result = toP(F.at(pos).ModuleDef(mods, kind, name, directives));
         attach(result, dc);
         return result;
     }
@@ -3205,15 +3218,38 @@
             int pos = token.pos;
             if (token.name() == names.requires) {
                 nextToken();
-                boolean isPublic = false;
-                if (token.kind == PUBLIC) {
-                    isPublic = true;
+                boolean isTransitive = false;
+                boolean isStaticPhase = false;
+            loop:
+                while (true) {
+                    switch (token.kind) {
+                        case IDENTIFIER:
+                            if (token.name() == names.transitive && !isTransitive) {
+                                Token t1 = S.token(1);
+                                if (t1.kind == SEMI || t1.kind == DOT) {
+                                    break loop;
+                                }
+                                isTransitive = true;
+                                break;
+                            } else {
+                                break loop;
+                            }
+                        case STATIC:
+                            if (isStaticPhase) {
+                                error(token.pos, "repeated.modifier");
+                            }
+                            isStaticPhase = true;
+                            break;
+                        default:
+                            break loop;
+                    }
                     nextToken();
                 }
                 JCExpression moduleName = qualident(false);
                 accept(SEMI);
-                defs.append(toP(F.at(pos).Requires(isPublic, moduleName)));
-            } else if (token.name() == names.exports) {
+                defs.append(toP(F.at(pos).Requires(isTransitive, isStaticPhase, moduleName)));
+            } else if (token.name() == names.exports || token.name() == names.opens) {
+                boolean exports = token.name() == names.exports;
                 nextToken();
                 JCExpression pkgName = qualident(false);
                 List<JCExpression> moduleNames = null;
@@ -3222,15 +3258,21 @@
                     moduleNames = qualidentList(false);
                 }
                 accept(SEMI);
-                defs.append(toP(F.at(pos).Exports(pkgName, moduleNames)));
+                JCDirective d;
+                if (exports) {
+                    d = F.at(pos).Exports(pkgName, moduleNames);
+                } else {
+                    d = F.at(pos).Opens(pkgName, moduleNames);
+                }
+                defs.append(toP(d));
             } else if (token.name() == names.provides) {
                 nextToken();
                 JCExpression serviceName = qualident(false);
                 if (token.kind == IDENTIFIER && token.name() == names.with) {
                     nextToken();
-                    JCExpression implName = qualident(false);
+                    List<JCExpression> implNames = qualidentList(false);
                     accept(SEMI);
-                    defs.append(toP(F.at(pos).Provides(serviceName, implName)));
+                    defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
                 } else {
                     error(token.pos, "expected", "'" + names.with + "'");
                     skip(false, false, false, false);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index 2dd5844..34bf24d 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -872,6 +872,9 @@
 compiler.err.pkg.annotations.sb.in.package-info.java=\
     package annotations should be in file package-info.java
 
+compiler.err.no.pkg.in.module-info.java=\
+    package clauses should not be in file module-info.java
+
 # 0: symbol
 compiler.err.pkg.clashes.with.class.of.same.name=\
     package {0} clashes with class of same name
@@ -1463,6 +1466,14 @@
     {0} in {1} has been deprecated and marked for removal
 
 # 0: symbol
+compiler.warn.has.been.deprecated.module=\
+    module {0} has been deprecated
+
+# 0: symbol
+compiler.warn.has.been.deprecated.for.removal.module=\
+    module {0} has been deprecated and marked for removal
+
+# 0: symbol
 compiler.warn.sun.proprietary=\
     {0} is internal proprietary API and may be removed in a future release
 
@@ -1796,6 +1807,9 @@
     reached end of file while parsing
 
 ## The following are related in form, but do not easily fit the above paradigm.
+compiler.err.expected.module=\
+    ''module'' expected
+
 compiler.err.dot.class.expected=\
     ''.class'' expected
 
@@ -2747,8 +2761,23 @@
     duplicate requires: {0}
 
 # 0: symbol
-compiler.err.duplicate.exports=\
-    duplicate export: {0}
+compiler.err.conflicting.exports=\
+    duplicate or conflicting exports: {0}
+
+# 0: symbol
+compiler.err.conflicting.opens=\
+    duplicate or conflicting opens: {0}
+
+# 0: symbol
+compiler.err.conflicting.exports.to.module=\
+    duplicate or conflicting exports to module: {0}
+
+# 0: symbol
+compiler.err.conflicting.opens.to.module=\
+    duplicate or conflicting opens to module: {0}
+
+compiler.err.no.opens.unless.strong=\
+    ''opens'' only allowed in strong modules
 
 # 0: symbol, 1: symbol
 compiler.err.duplicate.provides=\
@@ -2763,7 +2792,11 @@
     the service implementation is an abstract class: {0}
 
 compiler.err.service.implementation.must.be.subtype.of.service.interface=\
-    the service implementation type must be a subtype of the service interface type
+    the service implementation type must be a subtype of the service interface type, or \
+    have a public static no-args method named "provider" returning the service implementation
+
+compiler.err.service.implementation.provider.return.must.be.subtype.of.service.interface=\
+    the "provider" method return type must be a subtype of the service interface type
 
 # 0: symbol
 compiler.err.service.implementation.is.inner=\
@@ -2799,6 +2832,14 @@
 compiler.misc.module.name.mismatch=\
     module name {0} does not match expected name {1}
 
+# 0: name
+compiler.err.module.non.zero.opens=\
+    open module {0} has non-zero opens_count
+
+# 0: name
+compiler.misc.module.non.zero.opens=\
+    open module {0} has non-zero opens_count
+
 compiler.err.module.decl.sb.in.module-info.java=\
     module declarations should be in a file named module-info.java
 
@@ -2859,6 +2900,9 @@
 compiler.err.addmods.all.module.path.invalid=\
     --add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module
 
+compiler.warn.addopens.ignored=\
+    --add-opens has no effect at compile time
+
 compiler.misc.locn.module_source_path=\
     module source path
 
@@ -2889,8 +2933,8 @@
 compiler.warn.leaks.not.accessible.unexported=\
     {0} {1} in module {2} is not exported
 # 0: kind name, 1: symbol, 2: symbol
-compiler.warn.leaks.not.accessible.not.required.public=\
-    {0} {1} in module {2} is not indirectly exported using 'requires public'
+compiler.warn.leaks.not.accessible.not.required.transitive=\
+    {0} {1} in module {2} is not indirectly exported using 'requires transitive'
 # 0: kind name, 1: symbol, 2: symbol
 compiler.warn.leaks.not.accessible.unexported.qualified=\
     {0} {1} in module {2} may not be visible to all clients that require this module
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties
index 52f363e..fe8659b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties
@@ -841,7 +841,7 @@
 
 ## All errors which do not refer to a particular line in the source code are
 ## preceded by this string.
-compiler.err.error=\u30A8\u30E9\u30FC: 
+compiler.err.error=\u30A8\u30E9\u30FC:
 
 # The following error messages do not refer to a line in the source code.
 compiler.err.cant.read.file={0}\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093
@@ -1021,7 +1021,7 @@
 ## Warning messages may also include the following prefix to identify a
 ## lint option
 # 0: option name
-compiler.warn.lintOption=[{0}] 
+compiler.warn.lintOption=[{0}]
 
 # 0: symbol
 compiler.warn.constant.SVUID=serialVersionUID\u306F\u30AF\u30E9\u30B9{0}\u306E\u5B9A\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties
index b7de2bf..becc754 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties
@@ -841,7 +841,7 @@
 
 ## All errors which do not refer to a particular line in the source code are
 ## preceded by this string.
-compiler.err.error=\u9519\u8BEF: 
+compiler.err.error=\u9519\u8BEF:
 
 # The following error messages do not refer to a line in the source code.
 compiler.err.cant.read.file=\u65E0\u6CD5\u8BFB\u53D6: {0}
@@ -927,7 +927,7 @@
 # 0: boolean, 1: symbol
 compiler.note.mref.stat.1=\u8F6C\u6362\u65B9\u6CD5\u5F15\u7528\n\u66FF\u4EE3 metafactory = {0}\nbridge \u65B9\u6CD5 = {1}
 
-compiler.note.note=\u6CE8: 
+compiler.note.note=\u6CE8:
 
 # 0: file name
 compiler.note.deprecated.filename={0}\u4F7F\u7528\u6216\u8986\u76D6\u4E86\u5DF2\u8FC7\u65F6\u7684 API\u3002
@@ -1016,12 +1016,12 @@
 ##
 
 ## All warning messages are preceded by the following string.
-compiler.warn.warning=\u8B66\u544A: 
+compiler.warn.warning=\u8B66\u544A:
 
 ## Warning messages may also include the following prefix to identify a
 ## lint option
 # 0: option name
-compiler.warn.lintOption=[{0}] 
+compiler.warn.lintOption=[{0}]
 
 # 0: symbol
 compiler.warn.constant.SVUID=serialVersionUID \u5728\u7C7B{0}\u4E2D\u5FC5\u987B\u662F\u5E38\u91CF
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
index 58f6296..9efc014 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
@@ -47,7 +47,10 @@
 
 import javax.tools.JavaFileManager.Location;
 
+import com.sun.source.tree.ModuleTree.ModuleKind;
 import com.sun.tools.javac.code.Directive.ExportsDirective;
+import com.sun.tools.javac.code.Directive.OpensDirective;
+import com.sun.tools.javac.code.Type.ModuleType;
 
 /**
  * Root class for abstract syntax tree nodes. It provides definitions
@@ -352,6 +355,7 @@
 
         MODULEDEF,
         EXPORTS,
+        OPENS,
         PROVIDES,
         REQUIRES,
         USES,
@@ -527,6 +531,16 @@
         @DefinedBy(Api.COMPILER_TREE)
         public Kind getKind() { return Kind.COMPILATION_UNIT; }
 
+        public JCModuleDecl getModuleDecl() {
+            for (JCTree tree : defs) {
+                if (tree.hasTag(MODULEDEF)) {
+                    return (JCModuleDecl) tree;
+                }
+            }
+
+            return null;
+        }
+
         @DefinedBy(Api.COMPILER_TREE)
         public JCPackageDecl getPackage() {
             // PackageDecl must be the first entry if it exists
@@ -2619,11 +2633,17 @@
     }
 
     public static class JCModuleDecl extends JCTree implements ModuleTree {
+        public JCModifiers mods;
+        public ModuleType type;
+        private final ModuleKind kind;
         public JCExpression qualId;
         public List<JCDirective> directives;
         public ModuleSymbol sym;
 
-        protected JCModuleDecl(JCExpression qualId, List<JCDirective> directives) {
+        protected JCModuleDecl(JCModifiers mods, ModuleKind kind,
+                JCExpression qualId, List<JCDirective> directives) {
+            this.mods = mods;
+            this.kind = kind;
             this.qualId = qualId;
             this.directives = directives;
         }
@@ -2637,6 +2657,16 @@
         }
 
         @Override @DefinedBy(Api.COMPILER_TREE)
+        public List<? extends AnnotationTree> getAnnotations() {
+            return mods.annotations;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public ModuleKind getModuleType() {
+            return kind;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
         public JCExpression getName() {
             return qualId;
         }
@@ -2677,7 +2707,7 @@
         }
 
         @Override @DefinedBy(Api.COMPILER_TREE)
-        public JCExpression getExportName() {
+        public JCExpression getPackageName() {
             return qualid;
         }
 
@@ -2693,18 +2723,58 @@
 
         @Override
         public Tag getTag() {
-            return EXPORTS;
+            return Tag.EXPORTS;
+        }
+    }
+
+    public static class JCOpens extends JCDirective
+            implements OpensTree {
+        public JCExpression qualid;
+        public List<JCExpression> moduleNames;
+        public OpensDirective directive;
+
+        protected JCOpens(JCExpression qualId, List<JCExpression> moduleNames) {
+            this.qualid = qualId;
+            this.moduleNames = moduleNames;
+        }
+
+        @Override
+        public void accept(Visitor v) { v.visitOpens(this); }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Kind getKind() {
+            return Kind.OPENS;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public JCExpression getPackageName() {
+            return qualid;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public List<JCExpression> getModuleNames() {
+            return moduleNames;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public <R, D> R accept(TreeVisitor<R, D> v, D d) {
+            return v.visitOpens(this, d);
+        }
+
+        @Override
+        public Tag getTag() {
+            return Tag.OPENS;
         }
     }
 
     public static class JCProvides extends JCDirective
             implements ProvidesTree {
         public JCExpression serviceName;
-        public JCExpression implName;
+        public List<JCExpression> implNames;
 
-        protected JCProvides(JCExpression serviceName, JCExpression implName) {
+        protected JCProvides(JCExpression serviceName, List<JCExpression> implNames) {
             this.serviceName = serviceName;
-            this.implName = implName;
+            this.implNames = implNames;
         }
 
         @Override
@@ -2726,8 +2796,8 @@
         }
 
         @Override @DefinedBy(Api.COMPILER_TREE)
-        public JCExpression getImplementationName() {
-            return implName;
+        public List<JCExpression> getImplementationNames() {
+            return implNames;
         }
 
         @Override
@@ -2738,12 +2808,14 @@
 
     public static class JCRequires extends JCDirective
             implements RequiresTree {
-        public boolean isPublic;
+        public boolean isTransitive;
+        public boolean isStaticPhase;
         public JCExpression moduleName;
         public RequiresDirective directive;
 
-        protected JCRequires(boolean isPublic, JCExpression moduleName) {
-            this.isPublic = isPublic;
+        protected JCRequires(boolean isTransitive, boolean isStaticPhase, JCExpression moduleName) {
+            this.isTransitive = isTransitive;
+            this.isStaticPhase = isStaticPhase;
             this.moduleName = moduleName;
         }
 
@@ -2761,8 +2833,13 @@
         }
 
         @Override @DefinedBy(Api.COMPILER_TREE)
-        public boolean isPublic() {
-            return isPublic;
+        public boolean isTransitive() {
+            return isTransitive;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public boolean isStatic() {
+            return isStaticPhase;
         }
 
         @Override @DefinedBy(Api.COMPILER_TREE)
@@ -2946,10 +3023,11 @@
         JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args);
         JCModifiers Modifiers(long flags, List<JCAnnotation> annotations);
         JCErroneous Erroneous(List<? extends JCTree> errs);
-        JCModuleDecl ModuleDef(JCExpression qualId, List<JCDirective> directives);
+        JCModuleDecl ModuleDef(JCModifiers mods, ModuleKind kind, JCExpression qualId, List<JCDirective> directives);
         JCExports Exports(JCExpression qualId, List<JCExpression> moduleNames);
-        JCProvides Provides(JCExpression serviceName, JCExpression implName);
-        JCRequires Requires(boolean isPublic, JCExpression qualId);
+        JCOpens Opens(JCExpression qualId, List<JCExpression> moduleNames);
+        JCProvides Provides(JCExpression serviceName, List<JCExpression> implNames);
+        JCRequires Requires(boolean isTransitive, boolean isStaticPhase, JCExpression qualId);
         JCUses Uses(JCExpression qualId);
         LetExpr LetExpr(List<JCVariableDecl> defs, JCExpression expr);
     }
@@ -3013,6 +3091,7 @@
         public void visitErroneous(JCErroneous that)         { visitTree(that); }
         public void visitModuleDef(JCModuleDecl that)        { visitTree(that); }
         public void visitExports(JCExports that)             { visitTree(that); }
+        public void visitOpens(JCOpens that)                 { visitTree(that); }
         public void visitProvides(JCProvides that)           { visitTree(that); }
         public void visitRequires(JCRequires that)           { visitTree(that); }
         public void visitUses(JCUses that)                   { visitTree(that); }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
index e4a98d3..23fdbbe 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
@@ -28,6 +28,7 @@
 import java.io.*;
 
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
+import com.sun.source.tree.ModuleTree.ModuleKind;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
@@ -441,6 +442,10 @@
     @Override
     public void visitModuleDef(JCModuleDecl tree) {
         try {
+            printAnnotations(tree.mods.annotations);
+            if (tree.getModuleType() == ModuleKind.OPEN) {
+                print("open ");
+            }
             print("module ");
             printExpr(tree.qualId);
             if (tree.directives == null) {
@@ -457,7 +462,11 @@
     @Override
     public void visitExports(JCExports tree) {
         try {
-            print("exports ");
+            if (tree.hasTag(EXPORTS)) {
+                print("exports ");
+            } else {
+                print("opens ");
+            }
             printExpr(tree.qualid);
             if (tree.moduleNames != null) {
                 print(" to ");
@@ -475,7 +484,7 @@
             print("provides ");
             printExpr(tree.serviceName);
             print(" with ");
-            printExpr(tree.implName);
+            printExprs(tree.implNames);
             print(";");
         } catch (IOException e) {
             throw new UncheckedIOException(e);
@@ -486,8 +495,10 @@
     public void visitRequires(JCRequires tree) {
         try {
             print("requires ");
-            if (tree.isPublic)
-                print("public ");
+            if (tree.isStaticPhase)
+                print("static ");
+            if (tree.isTransitive)
+                print("transitive ");
             printExpr(tree.moduleName);
             print(";");
         } catch (IOException e) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
index 6fa5dc8..f1aa04f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.tree;
 
 import com.sun.source.tree.*;
+import com.sun.source.tree.Tree.Kind;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.DefinedBy;
 import com.sun.tools.javac.util.DefinedBy.Api;
@@ -508,9 +509,10 @@
     @Override @DefinedBy(Api.COMPILER_TREE)
     public JCTree visitModule(ModuleTree node, P p) {
         JCModuleDecl t = (JCModuleDecl) node;
+        JCModifiers mods = copy(t.mods, p);
         JCExpression qualId = copy(t.qualId);
         List<JCDirective> directives = copy(t.directives);
-        return M.at(t.pos).ModuleDef(qualId, directives);
+        return M.at(t.pos).ModuleDef(mods, t.getModuleType(), qualId, directives);
     }
 
     @Override @DefinedBy(Api.COMPILER_TREE)
@@ -522,18 +524,26 @@
     }
 
     @Override @DefinedBy(Api.COMPILER_TREE)
+    public JCOpens visitOpens(OpensTree node, P p) {
+        JCOpens t = (JCOpens) node;
+        JCExpression qualId = copy(t.qualid, p);
+        List<JCExpression> moduleNames = copy(t.moduleNames, p);
+        return M.at(t.pos).Opens(qualId, moduleNames);
+    }
+
+    @Override @DefinedBy(Api.COMPILER_TREE)
     public JCProvides visitProvides(ProvidesTree node, P p) {
         JCProvides t = (JCProvides) node;
         JCExpression serviceName = copy(t.serviceName, p);
-        JCExpression implName = copy(t.implName, p);
-        return M.at(t.pos).Provides(serviceName, implName);
+        List<JCExpression> implNames = copy(t.implNames, p);
+        return M.at(t.pos).Provides(serviceName, implNames);
     }
 
     @Override @DefinedBy(Api.COMPILER_TREE)
     public JCRequires visitRequires(RequiresTree node, P p) {
         JCRequires t = (JCRequires) node;
         JCExpression moduleName = copy(t.moduleName, p);
-        return M.at(t.pos).Requires(t.isPublic, moduleName);
+        return M.at(t.pos).Requires(t.isTransitive, t.isStaticPhase, moduleName);
     }
 
     @Override @DefinedBy(Api.COMPILER_TREE)
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
index 5210067..b0f430b 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
@@ -378,6 +378,11 @@
             return Position.NOPOS;
 
         switch(tree.getTag()) {
+            case MODULEDEF: {
+                JCModuleDecl md = (JCModuleDecl)tree;
+                return md.mods.annotations.isEmpty() ? md.pos :
+                       md.mods.annotations.head.pos;
+            }
             case PACKAGEDEF: {
                 JCPackageDecl pd = (JCPackageDecl)tree;
                 return pd.annotations.isEmpty() ? pd.pos :
@@ -769,8 +774,9 @@
         switch (node.getTag()) {
         case TOPLEVEL:
             JCCompilationUnit cut = (JCCompilationUnit) node;
-            if (isModuleInfo(cut) && cut.defs.nonEmpty() && cut.defs.head.hasTag(MODULEDEF))
-                return symbolFor(cut.defs.head);
+            JCModuleDecl moduleDecl = cut.getModuleDecl();
+            if (isModuleInfo(cut) && moduleDecl != null)
+                return symbolFor(moduleDecl);
             return cut.packge;
         case MODULEDEF:
             return ((JCModuleDecl) node).sym;
@@ -1076,6 +1082,11 @@
         case TYPE_ANNOTATION:
             return Tree.Kind.TYPE_ANNOTATION;
 
+        case EXPORTS:
+            return Tree.Kind.EXPORTS;
+        case OPENS:
+            return Tree.Kind.OPENS;
+
         default:
             return null;
         }
@@ -1158,7 +1169,7 @@
 
     public static boolean isModuleInfo(JCCompilationUnit tree) {
         return tree.sourcefile.isNameCompatible("module-info", JavaFileObject.Kind.SOURCE)
-                && tree.defs.nonEmpty() && tree.defs.head.hasTag(MODULEDEF);
+                && tree.getModuleDecl() != null;
     }
 
     public static JCModuleDecl getModule(JCCompilationUnit t) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
index 59d3945..83e3d5f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
 
 import java.util.Iterator;
 
+import com.sun.source.tree.ModuleTree.ModuleKind;
+import com.sun.source.tree.Tree.Kind;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
@@ -538,8 +540,9 @@
     }
 
     @Override
-    public JCModuleDecl ModuleDef(JCExpression qualid, List<JCDirective> directives) {
-        JCModuleDecl tree = new JCModuleDecl(qualid, directives);
+    public JCModuleDecl ModuleDef(JCModifiers mods, ModuleKind kind,
+            JCExpression qualid, List<JCDirective> directives) {
+        JCModuleDecl tree = new JCModuleDecl(mods, kind, qualid, directives);
         tree.pos = pos;
         return tree;
     }
@@ -552,15 +555,22 @@
     }
 
     @Override
-    public JCProvides Provides(JCExpression serviceName, JCExpression implName) {
-        JCProvides tree = new JCProvides(serviceName, implName);
+    public JCOpens Opens(JCExpression qualId, List<JCExpression> moduleNames) {
+        JCOpens tree = new JCOpens(qualId, moduleNames);
         tree.pos = pos;
         return tree;
     }
 
     @Override
-    public JCRequires Requires(boolean isPublic, JCExpression qualId) {
-        JCRequires tree = new JCRequires(isPublic, qualId);
+    public JCProvides Provides(JCExpression serviceName, List<JCExpression> implNames) {
+        JCProvides tree = new JCProvides(serviceName, implNames);
+        tree.pos = pos;
+        return tree;
+    }
+
+    @Override
+    public JCRequires Requires(boolean isTransitive, boolean isStaticPhase, JCExpression qualId) {
+        JCRequires tree = new JCRequires(isTransitive, isStaticPhase, qualId);
         tree.pos = pos;
         return tree;
     }
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
index 506925c..68407fe 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,6 +73,7 @@
 
     @Override
     public void visitModuleDef(JCModuleDecl tree) {
+        scan(tree.mods);
         scan(tree.qualId);
         scan(tree.directives);
     }
@@ -84,9 +85,15 @@
     }
 
     @Override
+    public void visitOpens(JCOpens tree) {
+        scan(tree.qualid);
+        scan(tree.moduleNames);
+    }
+
+    @Override
     public void visitProvides(JCProvides tree) {
         scan(tree.serviceName);
-        scan(tree.implName);
+        scan(tree.implNames);
     }
 
     @Override
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java
index dd0315e..906c0cc 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ModuleHelper.java
@@ -51,4 +51,5 @@
             from.addExports(pack, to);
         }
     }
-}
\ No newline at end of file
+}
+
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
index 5d671de..3ac63d5 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
@@ -64,11 +64,14 @@
     public final Name _super;
     public final Name _this;
     public final Name exports;
+    public final Name opens;
     public final Name module;
     public final Name provides;
     public final Name requires;
     public final Name to;
+    public final Name transitive;
     public final Name uses;
+    public final Name open;
     public final Name with;
 
     // field and method names
@@ -101,6 +104,7 @@
     public final Name length;
     public final Name next;
     public final Name ordinal;
+    public final Name provider;
     public final Name serialVersionUID;
     public final Name toString;
     public final Name value;
@@ -146,6 +150,7 @@
     public final Name LocalVariableTypeTable;
     public final Name MethodParameters;
     public final Name Module;
+    public final Name ModuleVersion;
     public final Name RuntimeInvisibleAnnotations;
     public final Name RuntimeInvisibleParameterAnnotations;
     public final Name RuntimeInvisibleTypeAnnotations;
@@ -160,7 +165,6 @@
     public final Name Synthetic;
     public final Name Value;
     public final Name Varargs;
-    public final Name Version;
 
     // members of java.lang.annotation.ElementType
     public final Name ANNOTATION_TYPE;
@@ -168,6 +172,7 @@
     public final Name FIELD;
     public final Name LOCAL_VARIABLE;
     public final Name METHOD;
+    public final Name MODULE;
     public final Name PACKAGE;
     public final Name PARAMETER;
     public final Name TYPE;
@@ -220,11 +225,14 @@
         _super = fromString("super");
         _this = fromString("this");
         exports = fromString("exports");
+        opens = fromString("opens");
         module = fromString("module");
         provides = fromString("provides");
         requires = fromString("requires");
         to = fromString("to");
+        transitive = fromString("transitive");
         uses = fromString("uses");
+        open = fromString("open");
         with = fromString("with");
 
         // field and method names
@@ -257,6 +265,7 @@
         length = fromString("length");
         next = fromString("next");
         ordinal = fromString("ordinal");
+        provider = fromString("provider");
         serialVersionUID = fromString("serialVersionUID");
         toString = fromString("toString");
         value = fromString("value");
@@ -303,6 +312,7 @@
         LocalVariableTypeTable = fromString("LocalVariableTypeTable");
         MethodParameters = fromString("MethodParameters");
         Module = fromString("Module");
+        ModuleVersion = fromString("ModuleVersion");
         RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
         RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
         RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
@@ -317,7 +327,6 @@
         Synthetic = fromString("Synthetic");
         Value = fromString("Value");
         Varargs = fromString("Varargs");
-        Version = fromString("Version");
 
         // members of java.lang.annotation.ElementType
         ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
@@ -325,6 +334,7 @@
         FIELD = fromString("FIELD");
         LOCAL_VARIABLE = fromString("LOCAL_VARIABLE");
         METHOD = fromString("METHOD");
+        MODULE = fromString("MODULE");
         PACKAGE = fromString("PACKAGE");
         PARAMETER = fromString("PARAMETER");
         TYPE = fromString("TYPE");
diff --git a/langtools/src/jdk.compiler/share/classes/module-info.java b/langtools/src/jdk.compiler/share/classes/module-info.java
index 0b66b4d..3f7051b 100644
--- a/langtools/src/jdk.compiler/share/classes/module-info.java
+++ b/langtools/src/jdk.compiler/share/classes/module-info.java
@@ -28,7 +28,7 @@
  *  and its command line equivalent, <em>javac</em>, as well as <em>javah</em>.
  */
 module jdk.compiler {
-    requires public java.compiler;
+    requires transitive java.compiler;
 
     exports com.sun.source.doctree;
     exports com.sun.source.tree;
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java
index f29448a..8d84060 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java
@@ -110,7 +110,7 @@
  *        by including some or all of the modules dependencies. The value may be
  *        one of:
  *   <ul>
- *     <li> public -- each module specified explicitly on the command line is
+ *     <li> transitive -- each module specified explicitly on the command line is
  *          expanded to include the closure of its transitive dependencies
  *     <li> all    -- each module specified explicitly on the command line
  *          is expanded to include the closure of its transitive dependencies,
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
index ef7681c..905b080 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java
@@ -28,11 +28,18 @@
 import java.util.ArrayList;
 import java.util.EnumMap;
 import java.util.List;
+import java.util.SortedSet;
 
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+import com.sun.source.doctree.DocTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder;
 import jdk.javadoc.internal.doclets.toolkit.util.DeprecatedAPIListBuilder.DeprElementKind;
@@ -57,6 +64,8 @@
 
     private String getAnchorName(DeprElementKind kind) {
         switch (kind) {
+            case MODULE:
+                return "module";
             case PACKAGE:
                 return "package";
             case INTERFACE:
@@ -88,6 +97,8 @@
 
     private String getHeadingKey(DeprElementKind kind) {
         switch (kind) {
+            case MODULE:
+                return "doclet.Deprecated_Modules";
             case PACKAGE:
                 return "doclet.Deprecated_Packages";
             case INTERFACE:
@@ -119,6 +130,8 @@
 
     private String getSummaryKey(DeprElementKind kind) {
         switch (kind) {
+            case MODULE:
+                return "doclet.deprecated_modules";
             case PACKAGE:
                 return "doclet.deprecated_packages";
             case INTERFACE:
@@ -150,6 +163,8 @@
 
     private String getHeaderKey(DeprElementKind kind) {
         switch (kind) {
+            case MODULE:
+                return "doclet.Module";
             case PACKAGE:
                 return "doclet.Package";
             case INTERFACE:
@@ -197,6 +212,7 @@
         writerMap = new EnumMap<>(DeprElementKind.class);
         for (DeprElementKind kind : DeprElementKind.values()) {
             switch (kind) {
+                case MODULE:
                 case PACKAGE:
                 case INTERFACE:
                 case CLASS:
@@ -268,12 +284,16 @@
                 List<String> memberTableHeader = new ArrayList<>();
                 memberTableHeader.add(resources.getText(getHeaderKey(kind)));
                 memberTableHeader.add(resources.getText("doclet.Description"));
-                if (kind == DeprElementKind.PACKAGE)
+                if (kind == DeprElementKind.MODULE) {
+                    addModuleDeprecatedAPI(deprapi.getSet(kind),
+                            getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
+                } else if (kind == DeprElementKind.PACKAGE) {
                     addPackageDeprecatedAPI(deprapi.getSet(kind),
                             getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
-                else
+                } else {
                     writerMap.get(kind).addDeprecatedAPI(deprapi.getSet(kind),
                             getHeadingKey(kind), memberTableSummary, memberTableHeader, div);
+                }
             }
         }
         if (configuration.allowTag(HtmlTag.MAIN)) {
@@ -373,4 +393,88 @@
         Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.deprecatedLabel);
         return li;
     }
+
+    /**
+     * Add module deprecation information to the documentation tree
+     *
+     * @param deprMdles list of deprecated modules
+     * @param headingKey the caption for the deprecated module table
+     * @param tableSummary the summary for the deprecated module table
+     * @param tableHeader table headers for the deprecated module table
+     * @param contentTree the content tree to which the deprecated module table will be added
+     */
+    protected void addModuleDeprecatedAPI(SortedSet<Element> deprMdles, String headingKey,
+            String tableSummary, List<String> tableHeader, Content contentTree) {
+        if (deprMdles.size() > 0) {
+            Content caption = getTableCaption(configuration.getContent(headingKey));
+            Content table = (configuration.isOutputHtml5())
+                    ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
+                    : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
+            table.addContent(getSummaryTableHeader(tableHeader, "col"));
+            Content tbody = new HtmlTree(HtmlTag.TBODY);
+            boolean altColor = true;
+            for (Element e : deprMdles) {
+                ModuleElement mdle = (ModuleElement) e;
+                HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
+                        getModuleLink(mdle, new StringContent(mdle.getQualifiedName())));
+                HtmlTree tr = HtmlTree.TR(thRow);
+                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+                tdDesc.addStyle(HtmlStyle.colLast);
+                List<? extends DocTree> tags = utils.getDeprecatedTrees(mdle);
+                if (!tags.isEmpty()) {
+                    addInlineDeprecatedComment(mdle, tags.get(0), tdDesc);
+                }
+                tr.addContent(tdDesc);
+                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+                altColor = !altColor;
+                tbody.addContent(tr);
+            }
+            table.addContent(tbody);
+            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+            Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
+            contentTree.addContent(ul);
+        }
+    }
+
+    /**
+     * Add package deprecation information to the documentation tree
+     *
+     * @param deprPkgs list of deprecated packages
+     * @param headingKey the caption for the deprecated package table
+     * @param tableSummary the summary for the deprecated package table
+     * @param tableHeader table headers for the deprecated package table
+     * @param contentTree the content tree to which the deprecated package table will be added
+     */
+    protected void addPackageDeprecatedAPI(SortedSet<Element> deprPkgs, String headingKey,
+            String tableSummary, List<String> tableHeader, Content contentTree) {
+        if (deprPkgs.size() > 0) {
+            Content caption = getTableCaption(configuration.getContent(headingKey));
+            Content table = (configuration.isOutputHtml5())
+                    ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
+                    : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
+            table.addContent(getSummaryTableHeader(tableHeader, "col"));
+            Content tbody = new HtmlTree(HtmlTag.TBODY);
+            boolean altColor = true;
+            for (Element e : deprPkgs) {
+                PackageElement pkg = (PackageElement) e;
+                HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
+                        getPackageLink(pkg, getPackageName(pkg)));
+                HtmlTree tr = HtmlTree.TR(thRow);
+                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+                tdDesc.addStyle(HtmlStyle.colLast);
+                List<? extends DocTree> tags = utils.getDeprecatedTrees(pkg);
+                if (!tags.isEmpty()) {
+                    addInlineDeprecatedComment(pkg, tags.get(0), tdDesc);
+                }
+                tr.addContent(tdDesc);
+                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+                altColor = !altColor;
+                tbody.addContent(tr);
+            }
+            table.addContent(tbody);
+            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
+            Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
+            contentTree.addContent(ul);
+        }
+    }
 }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
index 4001944..47fbd2e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
@@ -1046,48 +1046,6 @@
     }
 
     /**
-     * Add package deprecation information to the documentation tree
-     *
-     * @param deprPkgs list of deprecated packages
-     * @param headingKey the caption for the deprecated package table
-     * @param tableSummary the summary for the deprecated package table
-     * @param tableHeader table headers for the deprecated package table
-     * @param contentTree the content tree to which the deprecated package table will be added
-     */
-    protected void addPackageDeprecatedAPI(SortedSet<Element> deprPkgs, String headingKey,
-            String tableSummary, List<String> tableHeader, Content contentTree) {
-        if (deprPkgs.size() > 0) {
-            Content caption = getTableCaption(configuration.getContent(headingKey));
-            Content table = (configuration.isOutputHtml5())
-                    ? HtmlTree.TABLE(HtmlStyle.deprecatedSummary, caption)
-                    : HtmlTree.TABLE(HtmlStyle.deprecatedSummary, tableSummary, caption);
-            table.addContent(getSummaryTableHeader(tableHeader, "col"));
-            Content tbody = new HtmlTree(HtmlTag.TBODY);
-            boolean altColor = true;
-            for (Element e : deprPkgs) {
-                PackageElement pkg = (PackageElement) e;
-                HtmlTree thRow = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
-                        getPackageLink(pkg, getPackageName(pkg)));
-                HtmlTree tr = HtmlTree.TR(thRow);
-                HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-                tdDesc.addStyle(HtmlStyle.colLast);
-                List<? extends DocTree> tags = utils.getDeprecatedTrees(pkg);
-                if (!tags.isEmpty()) {
-                    addInlineDeprecatedComment(pkg, tags.get(0), tdDesc);
-                }
-                tr.addContent(tdDesc);
-                tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                altColor = !altColor;
-                tbody.addContent(tr);
-            }
-            table.addContent(tbody);
-            Content li = HtmlTree.LI(HtmlStyle.blockList, table);
-            Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
-            contentTree.addContent(ul);
-        }
-    }
-
-    /**
      * Return the path to the class page for a typeElement.
      *
      * @param te   TypeElement for which the path is requested.
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
index 7821ba2..41cb2ce 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
@@ -364,10 +364,10 @@
      */
     protected static void addImplementsInfo(HtmlDocletWriter writer,
             ExecutableElement method, Content dl) {
-        if (writer.configuration.nocomment) {
+        Utils utils = writer.utils;
+        if (utils.isStatic(method) || writer.configuration.nocomment) {
             return;
         }
-        Utils utils = writer.utils;
         Contents contents = writer.contents;
         ImplementedMethods implementedMethodsFinder =
                 new ImplementedMethods(method, writer.configuration);
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
index bb1e903..702d20c 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
@@ -114,6 +114,7 @@
      *
      * @param heading the heading for the section
      */
+    @Override
     public Content getModuleHeader(String heading) {
         HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString()));
         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
@@ -126,6 +127,9 @@
         }
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.header);
+        Content annotationContent = new HtmlTree(HtmlTag.P);
+        addAnnotationInfo(mdle, annotationContent);
+        div.addContent(annotationContent);
         Content tHeading = HtmlTree.HEADING(HtmlConstants.TITLE_HEADING, true,
                 HtmlStyle.title, contents.moduleLabel);
         tHeading.addContent(Contents.SPACE);
@@ -143,6 +147,7 @@
     /**
      * Get the content header.
      */
+    @Override
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
         div.addStyle(HtmlStyle.contentContainer);
@@ -152,6 +157,7 @@
     /**
      * Get the summary section header.
      */
+    @Override
     public Content getSummaryHeader() {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
         li.addStyle(HtmlStyle.blockList);
@@ -163,6 +169,7 @@
      *
      * @param summaryContentTree the content tree to be added to the summary tree.
      */
+    @Override
     public Content getSummaryTree(Content summaryContentTree) {
         HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
         return ul;
@@ -225,7 +232,7 @@
      * Add the list of directives for the module.
      *
      * @param dirs the list of module directives
-     * @params tbody the content tree to which the list is added
+     * @param tbody the content tree to which the list is added
      */
     public void addList(List<ModuleElement.Directive> dirs, Content tbody) {
         boolean altColor = true;
@@ -238,6 +245,9 @@
                 case EXPORTS:
                     addExportedPackagesList((ModuleElement.ExportsDirective) direct, tbody, altColor);
                     break;
+                case OPENS:
+                    //XXX ignore for now
+                    break;
                 case USES:
                     addUsesList((ModuleElement.UsesDirective) direct, tbody, altColor);
                     break;
@@ -254,6 +264,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addModulesSummary(Content summaryContentTree) {
         List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.REQUIRES);
         if (dirs != null && !dirs.isEmpty()) {
@@ -307,6 +318,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addPackagesSummary(Content summaryContentTree) {
         List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.EXPORTS);
         if (dirs != null && !dirs.isEmpty()) {
@@ -376,6 +388,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addServicesSummary(Content summaryContentTree) {
         List<ModuleElement.Directive> usesDirs = directiveMap.get(DirectiveKind.USES);
         List<ModuleElement.Directive> providesDirs = directiveMap.get(DirectiveKind.PROVIDES);
@@ -459,33 +472,60 @@
      * @param altColor true if altColor style should be used or false if rowColor style should be used
      */
     public void addProvidesList(ModuleElement.ProvidesDirective direct, Content tbody, boolean altColor) {
-        TypeElement impl = direct.getImplementation();
-        TypeElement srv = direct.getService();
-        Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl));
-        Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
-        HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
-        thType.addContent(new HtmlTree(HtmlTag.BR));
-        thType.addContent("(");
-        HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
-        thType.addContent(implSpan);
-        thType.addContent(Contents.SPACE);
-        thType.addContent(implLinkContent);
-        thType.addContent(")");
-        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
-        tdDesc.addStyle(HtmlStyle.colLast);
-        addSummaryComment(srv, tdDesc);
-        HtmlTree tr = HtmlTree.TR(thType);
-        tr.addContent(tdDesc);
-        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-        tbody.addContent(tr);
+        List<? extends TypeElement> impls = direct.getImplementations();
+        for (TypeElement impl : impls) {
+            TypeElement srv = direct.getService();
+            Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl));
+            Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
+            HtmlTree thType = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, srvLinkContent);
+            thType.addContent(new HtmlTree(HtmlTag.BR));
+            thType.addContent("(");
+            HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, contents.implementation);
+            thType.addContent(implSpan);
+            thType.addContent(Contents.SPACE);
+            thType.addContent(implLinkContent);
+            thType.addContent(")");
+            HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+            tdDesc.addStyle(HtmlStyle.colLast);
+            addSummaryComment(srv, tdDesc);
+            HtmlTree tr = HtmlTree.TR(thType);
+            tr.addContent(tdDesc);
+            tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+            tbody.addContent(tr);
+        }
+    }
+
+    /**
+     * Add the module deprecation information to the documentation tree.
+     *
+     * @param div the content tree to which the deprecation information will be added
+     */
+    public void addDeprecationInfo(Content div) {
+        List<? extends DocTree> deprs = utils.getBlockTags(mdle, DocTree.Kind.DEPRECATED);
+        if (utils.isDeprecated(mdle)) {
+            CommentHelper ch = utils.getCommentHelper(mdle);
+            HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
+            deprDiv.addStyle(HtmlStyle.deprecatedContent);
+            Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, contents.deprecatedPhrase);
+            deprDiv.addContent(deprPhrase);
+            if (!deprs.isEmpty()) {
+                List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
+                if (!commentTags.isEmpty()) {
+                    addInlineDeprecatedComment(mdle, deprs.get(0), deprDiv);
+                }
+            }
+            div.addContent(deprDiv);
+        }
     }
 
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addModuleDescription(Content moduleContentTree) {
         if (!utils.getFullBody(mdle).isEmpty()) {
             Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree;
+            addDeprecationInfo(tree);
             tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION);
             tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION));
             addInlineComment(mdle, tree);
@@ -498,6 +538,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addModuleTags(Content moduleContentTree) {
         Content tree = (configuration.allowTag(HtmlTag.SECTION))
                 ? HtmlTree.SECTION()
@@ -513,6 +554,7 @@
      *
      * @param subDiv the content tree to which the summary detail links will be added
      */
+    @Override
     protected void addSummaryDetailLinks(Content subDiv) {
         Content div = HtmlTree.DIV(getNavSummaryLinks());
         subDiv.addContent(div);
@@ -560,6 +602,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addModuleContent(Content contentTree, Content moduleContentTree) {
         if (configuration.allowTag(HtmlTag.MAIN)) {
             mainTree.addContent(moduleContentTree);
@@ -572,6 +615,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void addModuleFooter(Content contentTree) {
         Content htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
                 ? HtmlTree.FOOTER()
@@ -633,6 +677,7 @@
      *
      * @return a content tree for the previous link
      */
+    @Override
     public Content getNavLinkPrevious() {
         Content li;
         if (prevModule == null) {
@@ -649,6 +694,7 @@
      *
      * @return a content tree for the next link
      */
+    @Override
     public Content getNavLinkNext() {
         Content li;
         if (nextModule == null) {
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java
index 35b8eed..a4ff308e 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
index a69ac46..00239a4 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties
@@ -71,6 +71,7 @@
 doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1}
 doclet.tag.invalid_usage=invalid usage of tag {0}
 doclet.Deprecated_API=Deprecated API
+doclet.Deprecated_Modules=Deprecated Modules
 doclet.Deprecated_Packages=Deprecated Packages
 doclet.Deprecated_Classes=Deprecated Classes
 doclet.Deprecated_Enums=Deprecated Enums
@@ -83,6 +84,7 @@
 doclet.Deprecated_Methods=Deprecated Methods
 doclet.Deprecated_Enum_Constants=Deprecated Enum Constants
 doclet.Deprecated_Annotation_Type_Members=Deprecated Annotation Type Elements
+doclet.deprecated_modules=deprecated modules
 doclet.deprecated_packages=deprecated packages
 doclet.deprecated_classes=deprecated classes
 doclet.deprecated_enums=deprecated enums
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
index bae6366..0d0432a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
@@ -99,7 +99,7 @@
 doclet.Subinterfaces=\u65E2\u77E5\u306E\u30B5\u30D6\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u30EA\u30B9\u30C8:
 doclet.Implementing_Classes=\u65E2\u77E5\u306E\u5B9F\u88C5\u30AF\u30E9\u30B9\u306E\u30EA\u30B9\u30C8:
 doclet.Functional_Interface=\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9
-doclet.Functional_Interface_Message=\u3053\u308C\u306F\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306A\u306E\u3067\u3001\u30E9\u30E0\u30C0\u5F0F\u307E\u305F\u306F\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u306E\u5272\u5F53\u3066\u30BF\u30FC\u30B2\u30C3\u30C8\u3068\u3057\u3066\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002 
+doclet.Functional_Interface_Message=\u3053\u308C\u306F\u6A5F\u80FD\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306A\u306E\u3067\u3001\u30E9\u30E0\u30C0\u5F0F\u307E\u305F\u306F\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u306E\u5272\u5F53\u3066\u30BF\u30FC\u30B2\u30C3\u30C8\u3068\u3057\u3066\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
 doclet.also=\u540C\u69D8\u306B
 doclet.Frames=\u30D5\u30EC\u30FC\u30E0
 doclet.No_Frames=\u30D5\u30EC\u30FC\u30E0\u306A\u3057
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DeprecatedAPIListBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DeprecatedAPIListBuilder.java
index bdfae9f..bde350a 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DeprecatedAPIListBuilder.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DeprecatedAPIListBuilder.java
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import javax.lang.model.element.Element;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 
@@ -51,6 +52,7 @@
     private final Configuration configuration;
     private final Utils utils;
     public static enum DeprElementKind {
+        MODULE,
         PACKAGE,
         INTERFACE,
         CLASS,
@@ -82,12 +84,19 @@
 
     /**
      * Build the sorted list of all the deprecated APIs in this run.
-     * Build separate lists for deprecated packages, classes, constructors,
+     * Build separate lists for deprecated modules, packages, classes, constructors,
      * methods and fields.
      *
      * @param configuration the current configuration of the doclet.
      */
     private void buildDeprecatedAPIInfo() {
+        SortedSet<ModuleElement> modules = configuration.modules;
+        SortedSet<Element> mset = deprecatedMap.get(DeprElementKind.MODULE);
+        for (Element me : modules) {
+            if (utils.isDeprecated(me)) {
+                mset.add(me);
+            }
+        }
         SortedSet<PackageElement> packages = configuration.packages;
         SortedSet<Element> pset = deprecatedMap.get(DeprElementKind.PACKAGE);
         for (Element pe : packages) {
@@ -95,7 +104,6 @@
                 pset.add(pe);
             }
         }
-        deprecatedMap.put(DeprElementKind.PACKAGE, pset);
         for (Element e : configuration.getIncludedTypeElements()) {
             TypeElement te = (TypeElement)e;
             SortedSet<Element> eset;
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
index ab34330..1adec89 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
@@ -495,10 +495,10 @@
     private Set<ModuleElement> getModuleRequires(ModuleElement mdle, boolean isPublic) {
         Set<ModuleElement> result = new HashSet<>();
         for (RequiresDirective rd : ElementFilter.requiresIn(mdle.getDirectives())) {
-            if (isPublic && rd.isPublic()) {
+            if (isPublic && rd.isTransitive()) {
                 result.add(rd.getDependency());
             }
-            if (!isPublic && !rd.isPublic()) {
+            if (!isPublic && !rd.isTransitive()) {
                 result.add(rd.getDependency());
             }
         }
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java
index 19811e4..2a60a07 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java
@@ -480,7 +480,7 @@
 
         void setExpandRequires(ToolOption opt, String arg) throws OptionException {
             switch (arg) {
-                case "public":
+                case "transitive":
                     jdtoolOpts.put(opt, AccessKind.PUBLIC);
                     break;
                 case "all":
diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties
index 89cfe16..a720cf3 100644
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties
@@ -81,8 +81,8 @@
 main.opt.expand.requires.desc=\
     Instructs the tool to expand the set of modules to be\n\
     documented. By default, only the modules given explicitly on\n\
-    the command line will be documented. A value of "public" will\n\
-    additionally include all "requires public" dependencies of\n\
+    the command line will be documented. A value of "transitive" will\n\
+    additionally include all "requires transitive" dependencies of\n\
     those modules. A value of "all" will include all dependencies\n\
     of those modules.
 
diff --git a/langtools/src/jdk.javadoc/share/classes/module-info.java b/langtools/src/jdk.javadoc/share/classes/module-info.java
index 89c5d72..cbac558 100644
--- a/langtools/src/jdk.javadoc/share/classes/module-info.java
+++ b/langtools/src/jdk.javadoc/share/classes/module-info.java
@@ -28,8 +28,8 @@
  *  and its command line equivalent, <em>javadoc</em>.
  */
 module jdk.javadoc {
-    requires public java.compiler;
-    requires public jdk.compiler;
+    requires transitive java.compiler;
+    requires transitive jdk.compiler;
     requires java.xml;
 
     exports com.sun.javadoc;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java
index fed0bed..3cb8c1f 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,20 +42,22 @@
     public static final String BootstrapMethods         = "BootstrapMethods";
     public static final String CharacterRangeTable      = "CharacterRangeTable";
     public static final String Code                     = "Code";
-    public static final String ConcealedPackages        = "ConcealedPackages";
     public static final String ConstantValue            = "ConstantValue";
     public static final String CompilationID            = "CompilationID";
     public static final String Deprecated               = "Deprecated";
     public static final String EnclosingMethod          = "EnclosingMethod";
     public static final String Exceptions               = "Exceptions";
-    public static final String Hashes                   = "Hashes";
     public static final String InnerClasses             = "InnerClasses";
     public static final String LineNumberTable          = "LineNumberTable";
     public static final String LocalVariableTable       = "LocalVariableTable";
     public static final String LocalVariableTypeTable   = "LocalVariableTypeTable";
-    public static final String MainClass                = "MainClass";
     public static final String MethodParameters         = "MethodParameters";
     public static final String Module                   = "Module";
+    public static final String ModuleHashes             = "ModuleHashes";
+    public static final String ModuleMainClass          = "ModuleMainClass";
+    public static final String ModulePackages           = "ModulePackages";
+    public static final String ModuleTarget             = "ModuleTarget";
+    public static final String ModuleVersion            = "ModuleVersion";
     public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
     public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
     public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@@ -69,8 +71,6 @@
     public static final String StackMap                 = "StackMap";
     public static final String StackMapTable            = "StackMapTable";
     public static final String Synthetic                = "Synthetic";
-    public static final String TargetPlatform           = "TargetPlatform";
-    public static final String Version                  = "Version";
 
     public static class Factory {
         public Factory() {
@@ -115,19 +115,21 @@
             standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class);
             standardAttributes.put(Code,              Code_attribute.class);
             standardAttributes.put(CompilationID,     CompilationID_attribute.class);
-            standardAttributes.put(ConcealedPackages, ConcealedPackages_attribute.class);
             standardAttributes.put(ConstantValue,     ConstantValue_attribute.class);
             standardAttributes.put(Deprecated,        Deprecated_attribute.class);
             standardAttributes.put(EnclosingMethod,   EnclosingMethod_attribute.class);
             standardAttributes.put(Exceptions,        Exceptions_attribute.class);
-            standardAttributes.put(Hashes,            Hashes_attribute.class);
             standardAttributes.put(InnerClasses,      InnerClasses_attribute.class);
             standardAttributes.put(LineNumberTable,   LineNumberTable_attribute.class);
             standardAttributes.put(LocalVariableTable, LocalVariableTable_attribute.class);
             standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class);
-            standardAttributes.put(MainClass,         MainClass_attribute.class);
             standardAttributes.put(MethodParameters,  MethodParameters_attribute.class);
             standardAttributes.put(Module,            Module_attribute.class);
+            standardAttributes.put(ModuleHashes,      ModuleHashes_attribute.class);
+            standardAttributes.put(ModuleMainClass,   ModuleMainClass_attribute.class);
+            standardAttributes.put(ModulePackages,    ModulePackages_attribute.class);
+            standardAttributes.put(ModuleTarget,      ModuleTarget_attribute.class);
+            standardAttributes.put(ModuleVersion,     ModuleVersion_attribute.class);
             standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
             standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
             standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
@@ -141,8 +143,6 @@
             standardAttributes.put(StackMap,          StackMap_attribute.class);
             standardAttributes.put(StackMapTable,     StackMapTable_attribute.class);
             standardAttributes.put(Synthetic,         Synthetic_attribute.class);
-            standardAttributes.put(TargetPlatform,    TargetPlatform_attribute.class);
-            standardAttributes.put(Version,           Version_attribute.class);
         }
 
         private Map<String,Class<? extends Attribute>> standardAttributes;
@@ -178,19 +178,21 @@
         R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p);
         R visitCode(Code_attribute attr, P p);
         R visitCompilationID(CompilationID_attribute attr, P p);
-        R visitConcealedPackages(ConcealedPackages_attribute attr, P p);
         R visitConstantValue(ConstantValue_attribute attr, P p);
         R visitDeprecated(Deprecated_attribute attr, P p);
         R visitEnclosingMethod(EnclosingMethod_attribute attr, P p);
         R visitExceptions(Exceptions_attribute attr, P p);
-        R visitHashes(Hashes_attribute attr, P p);
         R visitInnerClasses(InnerClasses_attribute attr, P p);
         R visitLineNumberTable(LineNumberTable_attribute attr, P p);
         R visitLocalVariableTable(LocalVariableTable_attribute attr, P p);
         R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p);
-        R visitMainClass(MainClass_attribute attr, P p);
         R visitMethodParameters(MethodParameters_attribute attr, P p);
         R visitModule(Module_attribute attr, P p);
+        R visitModuleHashes(ModuleHashes_attribute attr, P p);
+        R visitModuleMainClass(ModuleMainClass_attribute attr, P p);
+        R visitModulePackages(ModulePackages_attribute attr, P p);
+        R visitModuleTarget(ModuleTarget_attribute attr, P p);
+        R visitModuleVersion(ModuleVersion_attribute attr, P p);
         R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
         R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
         R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
@@ -204,7 +206,5 @@
         R visitStackMap(StackMap_attribute attr, P p);
         R visitStackMapTable(StackMapTable_attribute attr, P p);
         R visitSynthetic(Synthetic_attribute attr, P p);
-        R visitTargetPlatform(TargetPlatform_attribute attr, P p);
-        R visitVersion(Version_attribute attr, P p);
     }
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
index b4fad8a..c3b8d81 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java
@@ -55,6 +55,9 @@
 
     /**
      * Write a ClassFile data structure to a file.
+     * @param classFile the classfile object to be written
+     * @param f the file
+     * @throws IOException if an error occurs while writing the file
      */
     public void write(ClassFile classFile, File f) throws IOException {
         try (FileOutputStream f_out = new FileOutputStream(f)) {
@@ -64,6 +67,9 @@
 
     /**
      * Write a ClassFile data structure to a stream.
+     * @param classFile the classfile object to be written
+     * @param s the stream
+     * @throws IOException if an error occurs while writing the file
      */
     public void write(ClassFile classFile, OutputStream s) throws IOException {
         this.classFile = classFile;
@@ -419,7 +425,7 @@
         }
 
         @Override
-        public Void visitConcealedPackages(ConcealedPackages_attribute attr, ClassOutputStream out) {
+        public Void visitModulePackages(ModulePackages_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.packages_count);
             for (int i: attr.packages_index)
                 out.writeShort(i);
@@ -461,12 +467,15 @@
         }
 
         @Override
-        public Void visitHashes(Hashes_attribute attr, ClassOutputStream out) {
+        public Void visitModuleHashes(ModuleHashes_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.algorithm_index);
             out.writeShort(attr.hashes_table.length);
-            for (Hashes_attribute.Entry e: attr.hashes_table) {
-                out.writeShort(e.requires_index);
-                out.writeShort(e.hash_index);
+            for (ModuleHashes_attribute.Entry e: attr.hashes_table) {
+                out.writeShort(e.module_name_index);
+                out.writeShort(e.hash.length);
+                for (byte b: e.hash) {
+                    out.writeByte(b);
+                }
             }
             return null;
         }
@@ -534,33 +543,54 @@
         }
 
         @Override
-        public Void visitMainClass(MainClass_attribute attr, ClassOutputStream out) {
+        public Void visitModuleMainClass(ModuleMainClass_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.main_class_index);
             return null;
         }
 
         @Override
         public Void visitModule(Module_attribute attr, ClassOutputStream out) {
+            out.writeShort(attr.module_name);
+            out.writeShort(attr.module_flags);
+
             out.writeShort(attr.requires.length);
             for (Module_attribute.RequiresEntry e: attr.requires) {
                 out.writeShort(e.requires_index);
                 out.writeShort(e.requires_flags);
             }
+
             out.writeShort(attr.exports.length);
             for (Module_attribute.ExportsEntry e: attr.exports) {
                 out.writeShort(e.exports_index);
+                out.writeShort(e.exports_flags);
                 out.writeShort(e.exports_to_index.length);
                 for (int index: e.exports_to_index)
                     out.writeShort(index);
             }
+
+            out.writeShort(attr.opens.length);
+            for (Module_attribute.OpensEntry e: attr.opens) {
+                out.writeShort(e.opens_index);
+                out.writeShort(e.opens_flags);
+                out.writeShort(e.opens_to_index.length);
+                for (int index: e.opens_to_index)
+                    out.writeShort(index);
+            }
+
             out.writeShort(attr.uses_index.length);
-            for (int index: attr.uses_index)
+            for (int index: attr.uses_index) {
                 out.writeShort(index);
+            }
+
             out.writeShort(attr.provides.length);
             for (Module_attribute.ProvidesEntry e: attr.provides) {
                 out.writeShort(e.provides_index);
-                out.writeShort(e.with_index);
+                out.writeShort(e.with_count);
+                for (int with : e.with_index) {
+                    out.writeShort(with);
+                }
             }
+
             return null;
         }
 
@@ -656,7 +686,7 @@
         }
 
         @Override
-        public Void visitTargetPlatform(TargetPlatform_attribute attr, ClassOutputStream out) {
+        public Void visitModuleTarget(ModuleTarget_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.os_name_index);
             out.writeShort(attr.os_arch_index);
             out.writeShort(attr.os_version_index);
@@ -668,7 +698,7 @@
         }
 
         @Override
-        public Void visitVersion(Version_attribute attr, ClassOutputStream out) {
+        public Void visitModuleVersion(ModuleVersion_attribute attr, ClassOutputStream out) {
             out.writeShort(attr.version_index);
             return null;
         }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java
similarity index 67%
rename from langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java
rename to langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java
index a248ebc..c227f3d 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Hashes_attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleHashes_attribute.java
@@ -35,8 +35,8 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public class Hashes_attribute extends Attribute {
-    Hashes_attribute(ClassReader cr, int name_index, int length) throws IOException {
+public class ModuleHashes_attribute extends Attribute {
+    ModuleHashes_attribute(ClassReader cr, int name_index, int length) throws IOException {
         super(name_index, length);
         algorithm_index = cr.readUnsignedShort();
         hashes_table_length = cr.readUnsignedShort();
@@ -45,13 +45,13 @@
             hashes_table[i] = new Entry(cr);
     }
 
-    public Hashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table)
+    public ModuleHashes_attribute(ConstantPool constant_pool, int algorithm_index, Entry[] hashes_table)
             throws ConstantPoolException {
-        this(constant_pool.getUTF8Index(Attribute.Hashes), algorithm_index, hashes_table);
+        this(constant_pool.getUTF8Index(Attribute.ModuleHashes), algorithm_index, hashes_table);
     }
 
-    public Hashes_attribute(int name_index, int algorithm_index, Entry[] hashes_table) {
-        super(name_index, 4 + hashes_table.length * Entry.length());
+    public ModuleHashes_attribute(int name_index, int algorithm_index, Entry[] hashes_table) {
+        super(name_index, 2 + 2 + length(hashes_table));
         this.algorithm_index = algorithm_index;
         this.hashes_table_length = hashes_table.length;
         this.hashes_table = hashes_table;
@@ -59,7 +59,15 @@
 
     @Override
     public <R, D> R accept(Visitor<R, D> visitor, D data) {
-        return visitor.visitHashes(this, data);
+        return visitor.visitModuleHashes(this, data);
+    }
+
+    private static int length(Entry[] hashes_table) {
+        int len = 0;
+        for (Entry e: hashes_table) {
+            len += e.length();
+        }
+        return len;
     }
 
     public final int algorithm_index;
@@ -68,16 +76,20 @@
 
     public static class Entry {
         Entry(ClassReader cr) throws IOException {
-            requires_index = cr.readUnsignedShort();
-            hash_index = cr.readUnsignedShort();
+            module_name_index = cr.readUnsignedShort();
+            int hash_length = cr.readUnsignedShort();
+            hash = new byte[hash_length];
+            for (int i=0; i<hash_length; i++) {
+                hash[i] = (byte) cr.readUnsignedByte();
+            }
         }
 
-        public static int length() {
-            return 4;
+        public int length() {
+            return 4 + hash.length;
         }
 
-        public final int requires_index;
-        public final int hash_index;
+        public final int module_name_index;
+        public final byte[] hash;
     }
 
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleMainClass_attribute.java
similarity index 81%
rename from langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java
rename to langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleMainClass_attribute.java
index ccd4554..30ad2a8 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/MainClass_attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleMainClass_attribute.java
@@ -35,18 +35,18 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public class MainClass_attribute extends Attribute {
-    MainClass_attribute(ClassReader cr, int name_index, int length) throws IOException {
+public class ModuleMainClass_attribute extends Attribute {
+    ModuleMainClass_attribute(ClassReader cr, int name_index, int length) throws IOException {
         super(name_index, length);
         main_class_index = cr.readUnsignedShort();
     }
 
-    public MainClass_attribute(ConstantPool constant_pool, int mainClass_index)
+    public ModuleMainClass_attribute(ConstantPool constant_pool, int mainClass_index)
             throws ConstantPoolException {
-        this(constant_pool.getUTF8Index(Attribute.Version), mainClass_index);
+        this(constant_pool.getUTF8Index(Attribute.ModuleMainClass), mainClass_index);
     }
 
-    public MainClass_attribute(int name_index, int mainClass_index) {
+    public ModuleMainClass_attribute(int name_index, int mainClass_index) {
         super(name_index, 2);
         this.main_class_index = mainClass_index;
     }
@@ -57,7 +57,7 @@
 
     @Override
     public <R, D> R accept(Visitor<R, D> visitor, D data) {
-        return visitor.visitMainClass(this, data);
+        return visitor.visitModuleMainClass(this, data);
     }
 
     public final int main_class_index;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java
similarity index 82%
rename from langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java
rename to langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java
index dc56d7b..a6eb2ff 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConcealedPackages_attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModulePackages_attribute.java
@@ -35,8 +35,8 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public class ConcealedPackages_attribute extends Attribute {
-    ConcealedPackages_attribute(ClassReader cr, int name_index, int length)
+public class ModulePackages_attribute extends Attribute {
+    ModulePackages_attribute(ClassReader cr, int name_index, int length)
             throws IOException {
         super(name_index, length);
         packages_count = cr.readUnsignedShort();
@@ -45,15 +45,15 @@
             packages_index[i] = cr.readUnsignedShort();
     }
 
-    public ConcealedPackages_attribute(ConstantPool constant_pool,
-                                       int[] packages_index)
+    public ModulePackages_attribute(ConstantPool constant_pool,
+                              int[] packages_index)
             throws ConstantPoolException {
-        this(constant_pool.getUTF8Index(Attribute.ConcealedPackages),
+        this(constant_pool.getUTF8Index(Attribute.ModulePackages),
              packages_index);
     }
 
-    public ConcealedPackages_attribute(int name_index,
-                                       int[] packages_index) {
+    public ModulePackages_attribute(int name_index,
+                              int[] packages_index) {
         super(name_index, 2 + packages_index.length * 2);
         this.packages_count = packages_index.length;
         this.packages_index = packages_index;
@@ -66,7 +66,7 @@
 
     @Override
     public <R, D> R accept(Visitor<R, D> visitor, D data) {
-        return visitor.visitConcealedPackages(this, data);
+        return visitor.visitModulePackages(this, data);
     }
 
     public final int packages_count;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java
similarity index 90%
rename from langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java
rename to langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java
index ad469a5..630eac1 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TargetPlatform_attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleTarget_attribute.java
@@ -35,8 +35,8 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public class TargetPlatform_attribute extends Attribute {
-    TargetPlatform_attribute(ClassReader cr, int name_index, int length) throws IOException {
+public class ModuleTarget_attribute extends Attribute {
+    ModuleTarget_attribute(ClassReader cr, int name_index, int length) throws IOException {
         super(name_index, length);
         os_name_index = cr.readUnsignedShort();
         os_arch_index = cr.readUnsignedShort();
@@ -45,7 +45,7 @@
 
     @Override
     public <R, D> R accept(Visitor<R, D> visitor, D data) {
-        return visitor.visitTargetPlatform(this, data);
+        return visitor.visitModuleTarget(this, data);
     }
 
     public final int os_name_index;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleVersion_attribute.java
similarity index 81%
rename from langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java
rename to langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleVersion_attribute.java
index ed6b749..8415d79 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Version_attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ModuleVersion_attribute.java
@@ -35,25 +35,25 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public class Version_attribute extends Attribute {
-    Version_attribute(ClassReader cr, int name_index, int length) throws IOException {
+public class ModuleVersion_attribute extends Attribute {
+    ModuleVersion_attribute(ClassReader cr, int name_index, int length) throws IOException {
         super(name_index, length);
         version_index = cr.readUnsignedShort();
     }
 
-    public Version_attribute(ConstantPool constant_pool, int version_index)
+    public ModuleVersion_attribute(ConstantPool constant_pool, int version_index)
             throws ConstantPoolException {
-        this(constant_pool.getUTF8Index(Attribute.Version), version_index);
+        this(constant_pool.getUTF8Index(Attribute.ModuleVersion), version_index);
     }
 
-    public Version_attribute(int name_index, int version_index) {
+    public ModuleVersion_attribute(int name_index, int version_index) {
         super(name_index, 2);
         this.version_index = version_index;
     }
 
     @Override
     public <R, D> R accept(Visitor<R, D> visitor, D data) {
-        return visitor.visitVersion(this, data);
+        return visitor.visitModuleVersion(this, data);
     }
 
     public final int version_index;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java
index b20729f..85262fb 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Module_attribute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,24 +36,38 @@
  *  deletion without notice.</b>
  */
 public class Module_attribute extends Attribute {
-    public static final int ACC_PUBLIC    =   0x20;
-    public static final int ACC_SYNTHETIC = 0x1000;
-    public static final int ACC_MANDATED  = 0x8000;
+    public static final int ACC_TRANSITIVE      =   0x10;
+    public static final int ACC_STATIC_PHASE    =   0x20;
+    public static final int ACC_OPEN            =   0x20;
+    public static final int ACC_SYNTHETIC       = 0x1000;
+    public static final int ACC_MANDATED        = 0x8000;
 
     Module_attribute(ClassReader cr, int name_index, int length) throws IOException {
         super(name_index, length);
+
+        module_name = cr.readUnsignedShort();
+        module_flags = cr.readUnsignedShort();
+
         requires_count = cr.readUnsignedShort();
         requires = new RequiresEntry[requires_count];
         for (int i = 0; i < requires_count; i++)
             requires[i] = new RequiresEntry(cr);
+
         exports_count = cr.readUnsignedShort();
         exports = new ExportsEntry[exports_count];
         for (int i = 0; i < exports_count; i++)
             exports[i] = new ExportsEntry(cr);
+
+        opens_count = cr.readUnsignedShort();
+        opens = new OpensEntry[opens_count];
+        for (int i = 0; i < opens_count; i++)
+            opens[i] = new OpensEntry(cr);
+
         uses_count = cr.readUnsignedShort();
         uses_index = new int[uses_count];
         for (int i = 0; i < uses_count; i++)
             uses_index[i] = cr.readUnsignedShort();
+
         provides_count = cr.readUnsignedShort();
         provides = new ProvidesEntry[provides_count];
         for (int i = 0; i < provides_count; i++)
@@ -61,20 +75,26 @@
     }
 
     public Module_attribute(int name_index,
+            int module_name,
+            int module_flags,
             RequiresEntry[] requires,
             ExportsEntry[] exports,
+            OpensEntry[] opens,
             int[] uses,
             ProvidesEntry[] provides) {
         super(name_index, 2);
+        this.module_name = module_name;
+        this.module_flags = module_flags;
         requires_count = requires.length;
         this.requires = requires;
         exports_count = exports.length;
         this.exports = exports;
+        opens_count = opens.length;
+        this.opens = opens;
         uses_count = uses.length;
         this.uses_index = uses;
         provides_count = provides.length;
         this.provides = provides;
-
     }
 
     public String getUses(int index, ConstantPool constant_pool) throws ConstantPoolException {
@@ -87,10 +107,14 @@
         return visitor.visitModule(this, data);
     }
 
+    public final int module_name;
+    public final int module_flags;
     public final int requires_count;
     public final RequiresEntry[] requires;
     public final int exports_count;
     public final ExportsEntry[] exports;
+    public final int opens_count;
+    public final OpensEntry[] opens;
     public final int uses_count;
     public final int[] uses_index;
     public final int provides_count;
@@ -120,14 +144,16 @@
     public static class ExportsEntry {
         ExportsEntry(ClassReader cr) throws IOException {
             exports_index = cr.readUnsignedShort();
+            exports_flags = cr.readUnsignedShort();
             exports_to_count = cr.readUnsignedShort();
             exports_to_index = new int[exports_to_count];
             for (int i = 0; i < exports_to_count; i++)
                 exports_to_index[i] = cr.readUnsignedShort();
         }
 
-        public ExportsEntry(int index, int[] to) {
+        public ExportsEntry(int index, int flags, int[] to) {
             this.exports_index = index;
+            this.exports_flags = flags;
             this.exports_to_count = to.length;
             this.exports_to_index = to;
         }
@@ -137,24 +163,57 @@
         }
 
         public final int exports_index;
+        public final int exports_flags;
         public final int exports_to_count;
         public final int[] exports_to_index;
     }
 
+    public static class OpensEntry {
+        OpensEntry(ClassReader cr) throws IOException {
+            opens_index = cr.readUnsignedShort();
+            opens_flags = cr.readUnsignedShort();
+            opens_to_count = cr.readUnsignedShort();
+            opens_to_index = new int[opens_to_count];
+            for (int i = 0; i < opens_to_count; i++)
+                opens_to_index[i] = cr.readUnsignedShort();
+        }
+
+        public OpensEntry(int index, int flags, int[] to) {
+            this.opens_index = index;
+            this.opens_flags = flags;
+            this.opens_to_count = to.length;
+            this.opens_to_index = to;
+        }
+
+        public int length() {
+            return 4 + 2 * opens_to_index.length;
+        }
+
+        public final int opens_index;
+        public final int opens_flags;
+        public final int opens_to_count;
+        public final int[] opens_to_index;
+    }
+
     public static class ProvidesEntry {
         ProvidesEntry(ClassReader cr) throws IOException {
             provides_index = cr.readUnsignedShort();
-            with_index = cr.readUnsignedShort();
+            with_count = cr.readUnsignedShort();
+            with_index = new int[with_count];
+            for (int i = 0; i < with_count; i++)
+                with_index[i] = cr.readUnsignedShort();
         }
 
-        public ProvidesEntry(int provides, int with) {
+        public ProvidesEntry(int provides, int[] with) {
             this.provides_index = provides;
+            this.with_count = with.length;
             this.with_index = with;
         }
 
         public static final int length = 4;
 
         public final int provides_index;
-        public final int with_index;
+        public final int with_count;
+        public final int[] with_index;
     }
 }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java
index 562d419..45fc421 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java
@@ -34,7 +34,6 @@
 import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry;
 import com.sun.tools.classfile.Code_attribute;
 import com.sun.tools.classfile.CompilationID_attribute;
-import com.sun.tools.classfile.ConcealedPackages_attribute;
 import com.sun.tools.classfile.ConstantPool;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.ConstantValue_attribute;
@@ -42,15 +41,18 @@
 import com.sun.tools.classfile.Deprecated_attribute;
 import com.sun.tools.classfile.EnclosingMethod_attribute;
 import com.sun.tools.classfile.Exceptions_attribute;
-import com.sun.tools.classfile.Hashes_attribute;
 import com.sun.tools.classfile.InnerClasses_attribute;
 import com.sun.tools.classfile.InnerClasses_attribute.Info;
 import com.sun.tools.classfile.LineNumberTable_attribute;
 import com.sun.tools.classfile.LocalVariableTable_attribute;
 import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
-import com.sun.tools.classfile.MainClass_attribute;
 import com.sun.tools.classfile.MethodParameters_attribute;
 import com.sun.tools.classfile.Module_attribute;
+import com.sun.tools.classfile.ModuleHashes_attribute;
+import com.sun.tools.classfile.ModuleMainClass_attribute;
+import com.sun.tools.classfile.ModulePackages_attribute;
+import com.sun.tools.classfile.ModuleTarget_attribute;
+import com.sun.tools.classfile.ModuleVersion_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
 import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
@@ -64,8 +66,6 @@
 import com.sun.tools.classfile.StackMapTable_attribute;
 import com.sun.tools.classfile.StackMap_attribute;
 import com.sun.tools.classfile.Synthetic_attribute;
-import com.sun.tools.classfile.TargetPlatform_attribute;
-import com.sun.tools.classfile.Version_attribute;
 
 import static com.sun.tools.classfile.AccessFlags.*;
 
@@ -237,7 +237,7 @@
         return null;
     }
 
-    private String getJavaPackage(ConcealedPackages_attribute attr, int index) {
+    private String getJavaPackage(ModulePackages_attribute attr, int index) {
         try {
             return getJavaName(attr.getPackage(index, constant_pool));
         } catch (ConstantPoolException e) {
@@ -246,8 +246,8 @@
     }
 
     @Override
-    public Void visitConcealedPackages(ConcealedPackages_attribute attr, Void ignore) {
-        println("ConcealedPackages: ");
+    public Void visitModulePackages(ModulePackages_attribute attr, Void ignore) {
+        println("ModulePackages: ");
         indent(+1);
         for (int i = 0; i < attr.packages_count; i++) {
             print("#" + attr.packages_index[i]);
@@ -323,22 +323,24 @@
     }
 
     @Override
-    public Void visitHashes(Hashes_attribute attr, Void ignore) {
-        println("Hashes:");
+    public Void visitModuleHashes(ModuleHashes_attribute attr, Void ignore) {
+        println("ModuleHashes:");
         indent(+1);
         print("algorithm #" + attr.algorithm_index);
         tab();
         println("// " + getAlgorithm(attr));
-        for (Hashes_attribute.Entry e : attr.hashes_table) {
-            print("#" + e.requires_index + ", #" + e.hash_index);
+        for (ModuleHashes_attribute.Entry e : attr.hashes_table) {
+            print("#" + e.module_name_index);
             tab();
-            println("// " + getRequires(e) + ": " + getHash(e));
+            println("// " + getModuleName(e));
+            println("hash_length: " + e.hash.length);
+            println("hash: [" + toHex(e.hash) + "]");
         }
         indent(-1);
         return null;
     }
 
-    private String getAlgorithm(Hashes_attribute attr) {
+    private String getAlgorithm(ModuleHashes_attribute attr) {
         try {
             return constant_pool.getUTF8Value(attr.algorithm_index);
         } catch (ConstantPoolException e) {
@@ -346,17 +348,9 @@
         }
     }
 
-    private String getRequires(Hashes_attribute.Entry entry) {
+    private String getModuleName(ModuleHashes_attribute.Entry entry) {
         try {
-            return constant_pool.getUTF8Value(entry.requires_index);
-        } catch (ConstantPoolException e) {
-            return report(e);
-        }
-    }
-
-    private String getHash(Hashes_attribute.Entry entry) {
-        try {
-            return constant_pool.getUTF8Value(entry.hash_index);
+            return constant_pool.getUTF8Value(entry.module_name_index);
         } catch (ConstantPoolException e) {
             return report(e);
         }
@@ -456,15 +450,15 @@
     }
 
     @Override
-    public Void visitMainClass(MainClass_attribute attr, Void ignore) {
-        print("MainClass: #" + attr.main_class_index);
+    public Void visitModuleMainClass(ModuleMainClass_attribute attr, Void ignore) {
+        print("ModuleMainClass: #" + attr.main_class_index);
         tab();
         print("// " + getJavaClassName(attr));
         println();
         return null;
     }
 
-    private String getJavaClassName(MainClass_attribute a) {
+    private String getJavaClassName(ModuleMainClass_attribute a) {
         try {
             return getJavaName(a.getMainClassName(constant_pool));
         } catch (ConstantPoolException e) {
@@ -477,7 +471,6 @@
     @Override
     public Void visitMethodParameters(MethodParameters_attribute attr,
                                       Void ignore) {
-
         final String header = String.format(format, "Name", "Flags");
         println("MethodParameters:");
         indent(+1);
@@ -501,8 +494,25 @@
     public Void visitModule(Module_attribute attr, Void ignore) {
         println("Module:");
         indent(+1);
+
+        print(attr.module_name);
+        tab();
+        println("// " + constantWriter.stringValue(attr.module_name));
+
+        print(String.format("%x", attr.module_flags));
+        tab();
+        print("// ");
+        if ((attr.module_flags & Module_attribute.ACC_OPEN) != 0)
+            print(" ACC_OPEN");
+        if ((attr.module_flags & Module_attribute.ACC_MANDATED) != 0)
+            print(" ACC_MANDATED");
+        if ((attr.module_flags & Module_attribute.ACC_SYNTHETIC) != 0)
+            print(" ACC_SYNTHETIC");
+        println();
+
         printRequiresTable(attr);
         printExportsTable(attr);
+        printOpensTable(attr);
         printUsesTable(attr);
         printProvidesTable(attr);
         indent(-1);
@@ -511,63 +521,107 @@
 
     protected void printRequiresTable(Module_attribute attr) {
         Module_attribute.RequiresEntry[] entries = attr.requires;
-        println(entries.length + "\t// " + "requires");
+        print(entries.length);
+        tab();
+        println("// " + "requires");
         indent(+1);
         for (Module_attribute.RequiresEntry e: entries) {
-            print("#" + e.requires_index + "," +
-                    String.format("%x", e.requires_flags)+ "\t// requires");
-            if ((e.requires_flags & Module_attribute.ACC_PUBLIC) != 0)
-                print(" public");
+            print("#" + e.requires_index + "," + String.format("%x", e.requires_flags));
+            tab();
+            print("// " + constantWriter.stringValue(e.requires_index));
+            if ((e.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0)
+                print(" ACC_TRANSITIVE");
+            if ((e.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0)
+                print(" ACC_STATIC_PHASE");
             if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0)
-                print(" synthetic");
+                print(" ACC_SYNTHETIC");
             if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0)
-                print(" mandated");
-            println(" " + constantWriter.stringValue(e.requires_index));
+                print(" ACC_MANDATED");
+            println();
         }
         indent(-1);
     }
 
     protected void printExportsTable(Module_attribute attr) {
         Module_attribute.ExportsEntry[] entries = attr.exports;
-        println(entries.length + "\t// " + "exports");
+        print(entries.length);
+        tab();
+        println("// exports");
         indent(+1);
         for (Module_attribute.ExportsEntry e: entries) {
-            print("#" + e.exports_index + "\t// exports");
-            print(" " + constantWriter.stringValue(e.exports_index));
-            if (e.exports_to_index.length == 0) {
-                println();
-            } else {
-                println(" to ... " + e.exports_to_index.length);
-                indent(+1);
-                for (int to: e.exports_to_index) {
-                    println("#" + to + "\t// ... to " + constantWriter.stringValue(to));
-                }
-                indent(-1);
-            }
+            printExportOpenEntry(e.exports_index, e.exports_flags, e.exports_to_index);
         }
         indent(-1);
     }
 
+    protected void printOpensTable(Module_attribute attr) {
+        Module_attribute.OpensEntry[] entries = attr.opens;
+        print(entries.length);
+        tab();
+        println("// opens");
+        indent(+1);
+        for (Module_attribute.OpensEntry e: entries) {
+            printExportOpenEntry(e.opens_index, e.opens_flags, e.opens_to_index);
+        }
+        indent(-1);
+    }
+
+    protected void printExportOpenEntry(int index, int flags, int[] to_index) {
+        print("#" + index + "," + String.format("%x", flags));
+        tab();
+        print("// ");
+        print(constantWriter.stringValue(index));
+        if ((flags & Module_attribute.ACC_MANDATED) != 0)
+            print(" ACC_MANDATED");
+        if ((flags & Module_attribute.ACC_SYNTHETIC) != 0)
+            print(" ACC_SYNTHETIC");
+        if (to_index.length == 0) {
+            println();
+        } else {
+            println(" to ... " + to_index.length);
+            indent(+1);
+            for (int to: to_index) {
+                print("#" + to);
+                tab();
+                println("// ... to " + constantWriter.stringValue(to));
+            }
+            indent(-1);
+        }
+    }
+
     protected void printUsesTable(Module_attribute attr) {
         int[] entries = attr.uses_index;
-        println(entries.length + "\t// " + "uses services");
+        print(entries.length);
+        tab();
+        println("// " + "uses");
         indent(+1);
         for (int e: entries) {
-            println("#" + e + "\t// uses " + constantWriter.stringValue(e));
+            print("#" + e);
+            tab();
+            println("// " + constantWriter.stringValue(e));
         }
         indent(-1);
     }
 
     protected void printProvidesTable(Module_attribute attr) {
         Module_attribute.ProvidesEntry[] entries = attr.provides;
-        println(entries.length + "\t// " + "provides services");
+        print(entries.length);
+        tab();
+        println("// " + "provides");
         indent(+1);
         for (Module_attribute.ProvidesEntry e: entries) {
-            print("#" + e.provides_index + ",#" +
-                    e.with_index + "\t// provides ");
+            print("#" + e.provides_index);
+            tab();
+            print("// ");
             print(constantWriter.stringValue(e.provides_index));
-            print (" with ");
-            println(constantWriter.stringValue(e.with_index));
+            println(" with ... " + e.with_count);
+            indent(+1);
+            for (int with : e.with_index) {
+                print("#" + with);
+                tab();
+                println("// ... with " + constantWriter.stringValue(with));
+            }
+            indent(-1);
         }
         indent(-1);
     }
@@ -876,8 +930,8 @@
     }
 
     @Override
-    public Void visitTargetPlatform(TargetPlatform_attribute attr, Void ignore) {
-        println("TargetPlatform:");
+    public Void visitModuleTarget(ModuleTarget_attribute attr, Void ignore) {
+        println("ModuleTarget:");
         indent(+1);
         print("os_name: #" + attr.os_name_index);
         if (attr.os_name_index != 0) {
@@ -901,7 +955,7 @@
         return null;
     }
 
-    private String getOSName(TargetPlatform_attribute attr) {
+    private String getOSName(ModuleTarget_attribute attr) {
         try {
             return constant_pool.getUTF8Value(attr.os_name_index);
         } catch (ConstantPoolException e) {
@@ -909,7 +963,7 @@
         }
     }
 
-    private String getOSArch(TargetPlatform_attribute attr) {
+    private String getOSArch(ModuleTarget_attribute attr) {
         try {
             return constant_pool.getUTF8Value(attr.os_arch_index);
         } catch (ConstantPoolException e) {
@@ -917,7 +971,7 @@
         }
     }
 
-    private String getOSVersion(TargetPlatform_attribute attr) {
+    private String getOSVersion(ModuleTarget_attribute attr) {
         try {
             return constant_pool.getUTF8Value(attr.os_version_index);
         } catch (ConstantPoolException e) {
@@ -926,8 +980,8 @@
     }
 
     @Override
-    public Void visitVersion(Version_attribute attr, Void ignore) {
-        print("Version: #" + attr.version_index);
+    public Void visitModuleVersion(ModuleVersion_attribute attr, Void ignore) {
+        print("ModuleVersion: #" + attr.version_index);
         indent(+1);
         tab();
         println("// " + getVersion(attr));
@@ -935,7 +989,7 @@
         return null;
     }
 
-    private String getVersion(Version_attribute attr) {
+    private String getVersion(ModuleVersion_attribute attr) {
         try {
             return constant_pool.getUTF8Value(attr.version_index);
         } catch (ConstantPoolException e) {
@@ -962,6 +1016,14 @@
         return StringUtils.toUpperCase(s);
     }
 
+    static 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 final AnnotationWriter annotationWriter;
     private final CodeWriter codeWriter;
     private final ConstantWriter constantWriter;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java
index 4cf1b22..0cfea17 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.ConstantValue_attribute;
 import com.sun.tools.classfile.Descriptor;
-import com.sun.tools.classfile.DescriptorException;
+import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
 import com.sun.tools.classfile.Exceptions_attribute;
 import com.sun.tools.classfile.Field;
 import com.sun.tools.classfile.Method;
@@ -157,21 +157,36 @@
             indent(-1);
         }
 
-        String name = getJavaName(classFile);
         AccessFlags flags = cf.access_flags;
-
         writeModifiers(flags.getClassModifiers());
 
-        if (classFile.access_flags.is(AccessFlags.ACC_MODULE) && name.endsWith(".module-info")) {
-            print("module ");
-            print(name.replace(".module-info", ""));
+        if (classFile.access_flags.is(AccessFlags.ACC_MODULE)) {
+            Attribute attr = classFile.attributes.get(Attribute.Module);
+            if (attr instanceof Module_attribute) {
+                Module_attribute modAttr = (Module_attribute) attr;
+                String name;
+                try {
+                    name = getJavaName(constant_pool.getUTF8Value(modAttr.module_name));
+                } catch (ConstantPoolException e) {
+                    name = report(e);
+                }
+                if ((modAttr.module_flags & Module_attribute.ACC_OPEN) != 0) {
+                    print("open ");
+                }
+                print("module ");
+                print(name);
+            } else {
+                // fallback for malformed class files
+                print("class ");
+                print(getJavaName(classFile));
+            }
         } else {
             if (classFile.isClass())
                 print("class ");
             else if (classFile.isInterface())
                 print("interface ");
 
-            print(name);
+            print(getJavaName(classFile));
         }
 
         Signature_attribute sigAttr = getSignature(cf.attributes);
@@ -210,7 +225,23 @@
             indent(+1);
             println("minor version: " + cf.minor_version);
             println("major version: " + cf.major_version);
-            writeList("flags: ", flags.getClassFlags(), "\n");
+            writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getClassFlags(), "\n");
+            print("this_class: #" + cf.this_class);
+            if (cf.this_class != 0) {
+                tab();
+                print("// " + constantWriter.stringValue(cf.this_class));
+            }
+            println();
+            print("super_class: #" + cf.super_class);
+            if (cf.super_class != 0) {
+                tab();
+                print("// " + constantWriter.stringValue(cf.super_class));
+            }
+            println();
+            print("interfaces: " + cf.interfaces.length);
+            print(", fields: " + cf.fields.length);
+            print(", methods: " + cf.methods.length);
+            println(", attributes: " + cf.attributes.attrs.length);
             indent(-1);
             constantWriter.writeConstantPool();
         } else {
@@ -249,17 +280,20 @@
                 return builder.toString();
             }
 
+            @Override
             public StringBuilder visitSimpleType(SimpleType type, StringBuilder sb) {
                 sb.append(getJavaName(type.name));
                 return sb;
             }
 
+            @Override
             public StringBuilder visitArrayType(ArrayType type, StringBuilder sb) {
                 append(sb, type.elemType);
                 sb.append("[]");
                 return sb;
             }
 
+            @Override
             public StringBuilder visitMethodType(MethodType type, StringBuilder sb) {
                 appendIfNotEmpty(sb, "<", type.typeParamTypes, "> ");
                 append(sb, type.returnType);
@@ -268,6 +302,7 @@
                 return sb;
             }
 
+            @Override
             public StringBuilder visitClassSigType(ClassSigType type, StringBuilder sb) {
                 appendIfNotEmpty(sb, "<", type.typeParamTypes, ">");
                 if (isInterface) {
@@ -283,6 +318,7 @@
                 return sb;
             }
 
+            @Override
             public StringBuilder visitClassType(ClassType type, StringBuilder sb) {
                 if (type.outerType != null) {
                     append(sb, type.outerType);
@@ -293,6 +329,7 @@
                 return sb;
             }
 
+            @Override
             public StringBuilder visitTypeParamType(TypeParamType type, StringBuilder sb) {
                 sb.append(type.name);
                 String sep = " extends ";
@@ -312,6 +349,7 @@
                 return sb;
             }
 
+            @Override
             public StringBuilder visitWildcardType(WildcardType type, StringBuilder sb) {
                 switch (type.kind) {
                     case UNBOUNDED:
@@ -402,7 +440,7 @@
             println("descriptor: " + getValue(f.descriptor));
 
         if (options.verbose)
-            writeList("flags: ", flags.getFieldFlags(), "\n");
+            writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getFieldFlags(), "\n");
 
         if (options.showAllAttrs) {
             for (Attribute attr: f.attributes)
@@ -459,16 +497,20 @@
         if (methodType != null) {
             print(new JavaTypePrinter(false).printTypeArgs(methodType.typeParamTypes));
         }
-        if (getName(m).equals("<init>")) {
-            print(getJavaName(classFile));
-            print(getJavaParameterTypes(d, flags));
-        } else if (getName(m).equals("<clinit>")) {
-            print("{}");
-        } else {
-            print(getJavaReturnType(d));
-            print(" ");
-            print(getName(m));
-            print(getJavaParameterTypes(d, flags));
+        switch (getName(m)) {
+            case "<init>":
+                print(getJavaName(classFile));
+                print(getJavaParameterTypes(d, flags));
+                break;
+            case "<clinit>":
+                print("{}");
+                break;
+            default:
+                print(getJavaReturnType(d));
+                print(" ");
+                print(getName(m));
+                print(getJavaParameterTypes(d, flags));
+                break;
         }
 
         Attribute e_attr = m.attributes.get(Attribute.Exceptions);
@@ -499,7 +541,7 @@
         }
 
         if (options.verbose) {
-            writeList("flags: ", flags.getMethodFlags(), "\n");
+            writeList(String.format("flags: (0x%04x) ", flags.flags), flags.getMethodFlags(), "\n");
         }
 
         Code_attribute code = null;
@@ -555,15 +597,18 @@
         Module_attribute m = (Module_attribute) attr;
         for (Module_attribute.RequiresEntry entry: m.requires) {
             print("requires");
-            if ((entry.requires_flags & Module_attribute.ACC_PUBLIC) != 0)
-                print(" public");
+            if ((entry.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0)
+                print(" static");
+            if ((entry.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0)
+                print(" transitive");
             print(" ");
             print(getUTF8Value(entry.requires_index).replace('/', '.'));
             println(";");
         }
 
         for (Module_attribute.ExportsEntry entry: m.exports) {
-            print("exports ");
+            print("exports");
+            print(" ");
             print(getUTF8Value(entry.exports_index).replace('/', '.'));
             boolean first = true;
             for (int i: entry.exports_to_index) {
@@ -587,6 +632,32 @@
                 indent(-1);
         }
 
+        for (Module_attribute.OpensEntry entry: m.opens) {
+            print("opens");
+            print(" ");
+            print(getUTF8Value(entry.opens_index).replace('/', '.'));
+            boolean first = true;
+            for (int i: entry.opens_to_index) {
+                String mname;
+                try {
+                    mname = classFile.constant_pool.getUTF8Value(i).replace('/', '.');
+                } catch (ConstantPoolException e) {
+                    mname = report(e);
+                }
+                if (first) {
+                    println(" to");
+                    indent(+1);
+                    first = false;
+                } else {
+                    println(",");
+                }
+                print(mname);
+            }
+            println(";");
+            if (!first)
+                indent(-1);
+        }
+
         for (int entry: m.uses_index) {
             print("uses ");
             print(getClassName(entry).replace('/', '.'));
@@ -594,13 +665,22 @@
         }
 
         for (Module_attribute.ProvidesEntry entry: m.provides) {
-            print("provides ");
+            print("provides  ");
             print(getClassName(entry.provides_index).replace('/', '.'));
-            println(" with");
-            indent(+1);
-            print(getClassName(entry.with_index).replace('/', '.'));
+            boolean first = true;
+            for (int i: entry.with_index) {
+                if (first) {
+                    println(" with");
+                    indent(+1);
+                    first = false;
+                } else {
+                    println(",");
+                }
+                print(getClassName(i).replace('/', '.'));
+            }
             println(";");
-            indent(-1);
+            if (!first)
+                indent(-1);
         }
     }
 
@@ -679,7 +759,7 @@
             return getJavaName(d.getFieldType(constant_pool));
         } catch (ConstantPoolException e) {
             return report(e);
-        } catch (DescriptorException e) {
+        } catch (InvalidDescriptor e) {
             return report(e);
         }
     }
@@ -689,7 +769,7 @@
             return getJavaName(d.getReturnType(constant_pool));
         } catch (ConstantPoolException e) {
             return report(e);
-        } catch (DescriptorException e) {
+        } catch (InvalidDescriptor e) {
             return report(e);
         }
     }
@@ -699,7 +779,7 @@
             return getJavaName(adjustVarargs(flags, d.getParameterTypes(constant_pool)));
         } catch (ConstantPoolException e) {
             return report(e);
-        } catch (DescriptorException e) {
+        } catch (InvalidDescriptor e) {
             return report(e);
         }
     }
@@ -766,12 +846,16 @@
                     ConstantPool.CONSTANT_Integer_info info =
                             (ConstantPool.CONSTANT_Integer_info) cpInfo;
                     String t = d.getValue(constant_pool);
-                    if (t.equals("C")) { // character
-                        return getConstantCharValue((char) info.value);
-                    } else if (t.equals("Z")) { // boolean
-                        return String.valueOf(info.value == 1);
-                    } else { // other: assume integer
-                        return String.valueOf(info.value);
+                    switch (t) {
+                        case "C":
+                            // character
+                            return getConstantCharValue((char) info.value);
+                        case "Z":
+                            // boolean
+                            return String.valueOf(info.value == 1);
+                        default:
+                            // other: assume integer
+                            return String.valueOf(info.value);
                     }
                 }
 
@@ -823,10 +907,10 @@
         }
     }
 
-    private Options options;
-    private AttributeWriter attrWriter;
-    private CodeWriter codeWriter;
-    private ConstantWriter constantWriter;
+    private final Options options;
+    private final AttributeWriter attrWriter;
+    private final CodeWriter codeWriter;
+    private final ConstantWriter constantWriter;
     private ClassFile classFile;
     private URI uri;
     private long lastModified;
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/TraverseProc.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/TraverseProc.java
index 0b65d9f..72e4e06 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/TraverseProc.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/TraverseProc.java
@@ -136,7 +136,7 @@
         Set<PackageElement> set = new HashSet<>();
         for (ModuleElement m : mods) {
             for (ModuleElement.Directive dir : m.getDirectives()) {
-                if (dir.getKind() == ModuleElement.DirectiveKind.EXPORTS) {
+                if (dir.getKind() == ModuleElement.DirectiveKind.EXPORTS) { //XXX
                     ModuleElement.ExportsDirective exp = (ModuleElement.ExportsDirective)dir;
                     if (exp.getTargetModules() == null) {
                         set.add(exp.getPackage());
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
index 9ad023c..d1e07da 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java
@@ -25,6 +25,7 @@
 
 package com.sun.tools.jdeps;
 
+import com.sun.tools.classfile.AccessFlags;
 import com.sun.tools.classfile.ClassFile;
 import com.sun.tools.classfile.ConstantPoolException;
 import com.sun.tools.classfile.Dependencies.ClassFileError;
@@ -170,7 +171,9 @@
     protected Set<String> scan() {
         try {
             ClassFile cf = ClassFile.read(path);
-            return Collections.singleton(cf.getName());
+            String name = cf.access_flags.is(AccessFlags.ACC_MODULE)
+                ? "module-info" : cf.getName();
+            return Collections.singleton(name);
         } catch (ConstantPoolException|IOException e) {
             throw new ClassFileError(e);
         }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java
index fbcb9a0..71508e6 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java
@@ -37,6 +37,7 @@
 
 import java.io.IOException;
 import java.io.UncheckedIOException;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -175,6 +176,9 @@
             public Set<Location> call() throws Exception {
                 Set<Location> targets = new HashSet<>();
                 for (ClassFile cf : archive.reader().getClassFiles()) {
+                    if (cf.access_flags.is(AccessFlags.ACC_MODULE))
+                        continue;
+
                     String classFileName;
                     try {
                         classFileName = cf.getName();
@@ -216,9 +220,13 @@
     {
         ClassFile cf = archive.reader().getClassFile(name);
         if (cf == null) {
-            throw new IllegalArgumentException(archive.getName() + " does not contain " + name);
+            throw new IllegalArgumentException(archive.getName() +
+                " does not contain " + name);
         }
 
+        if (cf.access_flags.is(AccessFlags.ACC_MODULE))
+            return Collections.emptySet();
+
         Set<Location> targets = new HashSet<>();
         String cn;
         try {
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java
index 1941c14..c33ac26 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java
@@ -29,11 +29,9 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Deque;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedDeque;
@@ -263,7 +261,7 @@
 
     public static enum Info {
         REQUIRES,
-        REQUIRES_PUBLIC,
+        REQUIRES_TRANSITIVE,
         EXPORTED_API,
         MODULE_PRIVATE,
         QUALIFIED_EXPORTED_API,
@@ -288,7 +286,7 @@
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
-            if (info != Info.REQUIRES && info != Info.REQUIRES_PUBLIC)
+            if (info != Info.REQUIRES && info != Info.REQUIRES_TRANSITIVE)
                 sb.append(source).append("/");
 
             sb.append(name);
@@ -325,7 +323,7 @@
      * Returns a graph of module dependences.
      *
      * Each Node represents a module and each edge is a dependence.
-     * No analysis on "requires public".
+     * No analysis on "requires transitive".
      */
     public Graph<Node> moduleGraph() {
         Graph.Builder<Node> builder = new Graph.Builder<>();
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java
index 5e9450c..85aa1c6 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java
@@ -388,10 +388,10 @@
         }
 
         static void printEdges(PrintWriter out, Graph<String> graph,
-                               String node, Set<String> requiresPublic) {
+                               String node, Set<String> requiresTransitive) {
             graph.adjacentNodes(node).forEach(dn -> {
                 String attr = dn.equals("java.base") ? REQUIRES_BASE
-                        : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES);
+                        : (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
                 out.format("  \"%s\" -> \"%s\" [%s];%n", node, dn, attr);
             });
         }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
index 4415965..1f887bb 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
@@ -38,6 +38,8 @@
 import java.io.UncheckedIOException;
 import java.lang.module.Configuration;
 import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
@@ -408,7 +410,7 @@
                             }
 
                             @Override
-                            public void close() throws IOException {
+                            public void close() {
                             }
                         };
                     }
@@ -421,12 +423,18 @@
         }
 
         private ModuleDescriptor dropHashes(ModuleDescriptor md) {
-            ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name());
+            ModuleDescriptor.Builder builder = ModuleDescriptor.module(md.name());
             md.requires().forEach(builder::requires);
             md.exports().forEach(builder::exports);
-            md.provides().values().stream().forEach(builder::provides);
+            md.opens().forEach(builder::opens);
+            md.provides().stream().forEach(builder::provides);
             md.uses().stream().forEach(builder::uses);
-            builder.conceals(md.conceals());
+
+            Set<String> concealed = new HashSet<>(md.packages());
+            md.exports().stream().map(Exports::source).forEach(concealed::remove);
+            md.opens().stream().map(Opens::source).forEach(concealed::remove);
+            concealed.forEach(builder::contains);
+
             return builder.build();
         }
 
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
index 1f6539f..de37add 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
@@ -154,6 +154,7 @@
         ANALYZE_DEPS(""),
         GENERATE_DOT_FILE("-dotoutput", "--dot-output"),
         GENERATE_MODULE_INFO("--generate-module-info"),
+        GENERATE_OPEN_MODULE("--generate-open-module"),
         LIST_DEPS("--list-deps"),
         LIST_REDUCED_DEPS("--list-reduced-deps"),
         CHECK_MODULES("--check");
@@ -248,7 +249,15 @@
                 if (task.command != null) {
                     throw new BadArgs("err.command.set", task.command, opt);
                 }
-                task.command = task.genModuleInfo(Paths.get(arg));
+                task.command = task.genModuleInfo(Paths.get(arg), false);
+            }
+        },
+        new Option(true, CommandOption.GENERATE_OPEN_MODULE) {
+            void process(JdepsTask task, String opt, String arg) throws BadArgs {
+                if (task.command != null) {
+                    throw new BadArgs("err.command.set", task.command, opt);
+                }
+                task.command = task.genModuleInfo(Paths.get(arg), true);
             }
         },
         new Option(false, CommandOption.LIST_DEPS) {
@@ -597,11 +606,11 @@
         return new GenDotFile(dir);
     }
 
-    private GenModuleInfo genModuleInfo(Path dir) throws BadArgs {
+    private GenModuleInfo genModuleInfo(Path dir, boolean openModule) throws BadArgs {
         if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
             throw new BadArgs("err.invalid.path", dir.toString());
         }
-        return new GenModuleInfo(dir);
+        return new GenModuleInfo(dir, openModule);
     }
 
     private ListModuleDeps listModuleDeps(boolean reduced) throws BadArgs {
@@ -829,9 +838,11 @@
 
     class GenModuleInfo extends Command {
         final Path dir;
-        GenModuleInfo(Path dir) {
+        final boolean openModule;
+        GenModuleInfo(Path dir, boolean openModule) {
             super(CommandOption.GENERATE_MODULE_INFO);
             this.dir = dir;
+            this.openModule = openModule;
         }
 
         @Override
@@ -872,7 +883,7 @@
             }
 
             ModuleInfoBuilder builder
-                 = new ModuleInfoBuilder(config, inputArgs, dir);
+                 = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
             boolean ok = builder.run();
 
             if (!ok && !options.nowarning) {
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
index f00394a..e49a7f7 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java
@@ -26,6 +26,8 @@
 package com.sun.tools.jdeps;
 
 import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
 import java.net.URI;
 import java.util.Collections;
 import java.util.HashMap;
@@ -240,18 +242,24 @@
         private StrictModule(Module m, Map<String, Boolean> requires) {
             super(m.name(), m.location, m.descriptor, m.exports, m.isSystem, m.reader());
 
-            ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(m.name());
+            ModuleDescriptor.Builder builder = ModuleDescriptor.module(m.name());
             requires.keySet().forEach(mn -> {
                 if (requires.get(mn).equals(Boolean.TRUE)) {
-                    builder.requires(ModuleDescriptor.Requires.Modifier.PUBLIC, mn);
+                    builder.requires(Set.of(ModuleDescriptor.Requires.Modifier.TRANSITIVE), mn);
                 } else {
                     builder.requires(mn);
                 }
             });
             m.descriptor.exports().forEach(e -> builder.exports(e));
+            m.descriptor.opens().forEach(o -> builder.opens(o));
             m.descriptor.uses().forEach(s -> builder.uses(s));
-            m.descriptor.provides().values().forEach(p -> builder.provides(p));
-            builder.conceals(m.descriptor.conceals());
+            m.descriptor.provides().forEach(p -> builder.provides(p));
+
+            Set<String> concealed = new HashSet<>(m.descriptor.packages());
+            m.descriptor.exports().stream().map(Exports::source).forEach(concealed::remove);
+            m.descriptor.opens().stream().map(Opens::source).forEach(concealed::remove);
+            concealed.forEach(builder::contains);
+
             this.md = builder.build();
         }
 
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java
index 9c0d65c..6da1628 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java
@@ -87,8 +87,8 @@
 
     public boolean run() throws IOException {
         try {
-            // compute "requires public" dependences
-            modules.values().forEach(ModuleDeps::computeRequiresPublic);
+            // compute "requires transitive" dependences
+            modules.values().forEach(ModuleDeps::computeRequiresTransitive);
 
             modules.values().forEach(md -> {
                 // compute "requires" dependences
@@ -104,7 +104,7 @@
 
     class ModuleDeps {
         final Module root;
-        Set<Module> requiresPublic;
+        Set<Module> requiresTransitive;
         Set<Module> requires;
         Map<String, Set<String>> unusedQualifiedExports;
 
@@ -113,15 +113,15 @@
         }
 
         /**
-         * Compute 'requires public' dependences by analyzing API dependencies
+         * Compute 'requires transitive' dependences by analyzing API dependencies
          */
-        private void computeRequiresPublic() {
-            // record requires public
-            this.requiresPublic = computeRequires(true)
+        private void computeRequiresTransitive() {
+            // record requires transitive
+            this.requiresTransitive = computeRequires(true)
                 .filter(m -> !m.name().equals(JAVA_BASE))
                 .collect(toSet());
 
-            trace("requires public: %s%n", requiresPublic);
+            trace("requires transitive: %s%n", requiresTransitive);
         }
 
         private void computeRequires() {
@@ -144,24 +144,24 @@
         }
 
         ModuleDescriptor descriptor() {
-            return descriptor(requiresPublic, requires);
+            return descriptor(requiresTransitive, requires);
         }
 
-        private ModuleDescriptor descriptor(Set<Module> requiresPublic,
+        private ModuleDescriptor descriptor(Set<Module> requiresTransitive,
                                             Set<Module> requires) {
 
-            ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(root.name());
+            ModuleDescriptor.Builder builder = ModuleDescriptor.module(root.name());
 
             if (!root.name().equals(JAVA_BASE))
-                builder.requires(MANDATED, JAVA_BASE);
+                builder.requires(Set.of(MANDATED), JAVA_BASE);
 
-            requiresPublic.stream()
+            requiresTransitive.stream()
                 .filter(m -> !m.name().equals(JAVA_BASE))
                 .map(Module::name)
-                .forEach(mn -> builder.requires(PUBLIC, mn));
+                .forEach(mn -> builder.requires(Set.of(TRANSITIVE), mn));
 
             requires.stream()
-                .filter(m -> !requiresPublic.contains(m))
+                .filter(m -> !requiresTransitive.contains(m))
                 .filter(m -> !m.name().equals(JAVA_BASE))
                 .map(Module::name)
                 .forEach(mn -> builder.requires(mn));
@@ -172,10 +172,10 @@
         private Graph<Module> buildReducedGraph() {
             ModuleGraphBuilder rpBuilder = new ModuleGraphBuilder(configuration);
             rpBuilder.addModule(root);
-            requiresPublic.stream()
+            requiresTransitive.stream()
                           .forEach(m -> rpBuilder.addEdge(root, m));
 
-            // requires public graph
+            // requires transitive graph
             Graph<Module> rbg = rpBuilder.build().reduce();
 
             ModuleGraphBuilder gb = new ModuleGraphBuilder(configuration);
@@ -198,7 +198,7 @@
          */
         ModuleDescriptor reduced() {
             Graph<Module> g = buildReducedGraph();
-            return descriptor(requiresPublic, g.adjacentNodes(root));
+            return descriptor(requiresTransitive, g.adjacentNodes(root));
         }
 
         /**
@@ -309,16 +309,16 @@
     }
 
     private boolean matches(ModuleDescriptor md, ModuleDescriptor other) {
-        // build requires public from ModuleDescriptor
-        Set<ModuleDescriptor.Requires> reqPublic = md.requires().stream()
-            .filter(req -> req.modifiers().contains(PUBLIC))
+        // build requires transitive from ModuleDescriptor
+        Set<ModuleDescriptor.Requires> reqTransitive = md.requires().stream()
+            .filter(req -> req.modifiers().contains(TRANSITIVE))
             .collect(toSet());
-        Set<ModuleDescriptor.Requires> otherReqPublic = other.requires().stream()
-            .filter(req -> req.modifiers().contains(PUBLIC))
+        Set<ModuleDescriptor.Requires> otherReqTransitive = other.requires().stream()
+            .filter(req -> req.modifiers().contains(TRANSITIVE))
             .collect(toSet());
 
-        if (!reqPublic.equals(otherReqPublic)) {
-            trace("mismatch requires public: %s%n", reqPublic);
+        if (!reqTransitive.equals(otherReqTransitive)) {
+            trace("mismatch requires transitive: %s%n", reqTransitive);
             return false;
         }
 
@@ -365,12 +365,12 @@
                 .sorted(Comparator.comparing(ModuleDescriptor::name))
                 .forEach(md -> {
                     String mn = md.name();
-                    Set<String> requiresPublic = md.requires().stream()
-                        .filter(d -> d.modifiers().contains(PUBLIC))
+                    Set<String> requiresTransitive = md.requires().stream()
+                        .filter(d -> d.modifiers().contains(TRANSITIVE))
                         .map(d -> d.name())
                         .collect(toSet());
 
-                    DotGraph.printEdges(out, graph, mn, requiresPublic);
+                    DotGraph.printEdges(out, graph, mn, requiresTransitive);
                 });
 
             out.println("}");
@@ -380,20 +380,20 @@
     /**
      * Returns a Graph of the given Configuration after transitive reduction.
      *
-     * Transitive reduction of requires public edge and requires edge have
-     * to be applied separately to prevent the requires public edges
+     * Transitive reduction of requires transitive edge and requires edge have
+     * to be applied separately to prevent the requires transitive edges
      * (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V)
      * in which  V would not be re-exported from U.
      */
     private Graph<String> gengraph(Set<Module> modules) {
-        // build a Graph containing only requires public edges
+        // build a Graph containing only requires transitive edges
         // with transitive reduction.
         Graph.Builder<String> rpgbuilder = new Graph.Builder<>();
         for (Module module : modules) {
             ModuleDescriptor md = module.descriptor();
             String mn = md.name();
             md.requires().stream()
-                    .filter(d -> d.modifiers().contains(PUBLIC))
+                    .filter(d -> d.modifiers().contains(TRANSITIVE))
                     .map(d -> d.name())
                     .forEach(d -> rpgbuilder.addEdge(mn, d));
         }
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java
index 8d7b820..056b53f 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java
@@ -178,7 +178,7 @@
         RootModule(String name) {
             super(name);
 
-            ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(name);
+            ModuleDescriptor.Builder builder = ModuleDescriptor.module(name);
             this.descriptor = builder.build();
         }
 
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleGraphBuilder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleGraphBuilder.java
index 4352963..812f9be 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleGraphBuilder.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleGraphBuilder.java
@@ -98,7 +98,7 @@
             });
         });
 
-        // read requires public from ModuleDescriptor
+        // read requires transitive from ModuleDescriptor
         Module source;
         while ((source = deque.poll()) != null) {
             if (visited.contains(source))
@@ -107,7 +107,7 @@
             visited.add(source);
             builder.addNode(source);
             Module from = source;
-            requiresPublic(from).forEach(m -> {
+            requiresTransitive(from).forEach(m -> {
                 deque.add(m);
                 builder.addEdge(from, m);
             });
@@ -116,13 +116,13 @@
     }
 
     /*
-     * Returns a stream of modules upon which the given module `requires public`
+     * Returns a stream of modules upon which the given module `requires transitive`
      */
-    public Stream<Module> requiresPublic(Module m) {
-        // find requires public
+    public Stream<Module> requiresTransitive(Module m) {
+        // find requires transitive
         return m.descriptor()
                 .requires().stream()
-                .filter(req -> req.modifiers().contains(PUBLIC))
+                .filter(req -> req.modifiers().contains(TRANSITIVE))
                 .map(ModuleDescriptor.Requires::name)
                 .map(config::findModule)
                 .flatMap(Optional::stream);
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
index ab493a6..06a31cd 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
@@ -47,13 +47,14 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import static java.util.stream.Collectors.*;
 
 
 public class ModuleInfoBuilder {
     final JdepsConfiguration configuration;
     final Path outputdir;
+    final boolean open;
 
     final DependencyFinder dependencyFinder;
     final Analyzer analyzer;
@@ -63,9 +64,11 @@
     final Map<Module, Module> automaticToExplicitModule;
     public ModuleInfoBuilder(JdepsConfiguration configuration,
                              List<String> args,
-                             Path outputdir) {
+                             Path outputdir,
+                             boolean open) {
         this.configuration = configuration;
         this.outputdir = outputdir;
+        this.open = open;
 
         this.dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER);
         this.analyzer = new Analyzer(configuration, Type.CLASS, DEFAULT_FILTER);
@@ -73,13 +76,13 @@
         // add targets to modulepath if it has module-info.class
         List<Path> paths = args.stream()
             .map(fn -> Paths.get(fn))
-            .collect(Collectors.toList());
+            .collect(toList());
 
         // automatic module to convert to explicit module
         this.automaticToExplicitModule = ModuleFinder.of(paths.toArray(new Path[0]))
                 .findAll().stream()
                 .map(configuration::toModule)
-                .collect(Collectors.toMap(Function.identity(), Function.identity()));
+                .collect(toMap(Function.identity(), Function.identity()));
 
         Optional<Module> om = automaticToExplicitModule.keySet().stream()
                                     .filter(m -> !m.descriptor().isAutomatic())
@@ -96,7 +99,7 @@
     public boolean run() throws IOException {
         try {
             // pass 1: find API dependencies
-            Map<Archive, Set<Archive>> requiresPublic = computeRequiresPublic();
+            Map<Archive, Set<Archive>> requiresTransitive = computeRequiresTransitive();
 
             // pass 2: analyze all class dependences
             dependencyFinder.parse(automaticModules().stream());
@@ -105,13 +108,13 @@
 
             boolean missingDeps = false;
             for (Module m : automaticModules()) {
-                Set<Archive> apiDeps = requiresPublic.containsKey(m)
-                                            ? requiresPublic.get(m)
+                Set<Archive> apiDeps = requiresTransitive.containsKey(m)
+                                            ? requiresTransitive.get(m)
                                             : Collections.emptySet();
 
                 Path file = outputdir.resolve(m.name()).resolve("module-info.java");
 
-                // computes requires and requires public
+                // computes requires and requires transitive
                 Module explicitModule = toExplicitModule(m, apiDeps);
                 if (explicitModule != null) {
                     automaticToExplicitModule.put(m, explicitModule);
@@ -136,7 +139,7 @@
         return m == NOT_FOUND || m == REMOVED_JDK_INTERNALS;
     }
 
-    private Module toExplicitModule(Module module, Set<Archive> requiresPublic)
+    private Module toExplicitModule(Module module, Set<Archive> requiresTransitive)
         throws IOException
     {
         // done analysis
@@ -148,7 +151,7 @@
         }
 
         Map<String, Boolean> requires = new HashMap<>();
-        requiresPublic.stream()
+        requiresTransitive.stream()
             .map(Archive::getModule)
             .forEach(m -> requires.put(m.name(), Boolean.TRUE));
 
@@ -183,53 +186,60 @@
             });
     }
 
-    void writeModuleInfo(Path file, ModuleDescriptor descriptor) {
+    void writeModuleInfo(Path file, ModuleDescriptor md) {
         try {
             Files.createDirectories(file.getParent());
             try (PrintWriter pw = new PrintWriter(Files.newOutputStream(file))) {
-                printModuleInfo(pw, descriptor);
+                printModuleInfo(pw, md);
             }
         } catch (IOException e) {
             throw new UncheckedIOException(e);
         }
     }
 
-    private void printModuleInfo(PrintWriter writer, ModuleDescriptor descriptor) {
-        writer.format("module %s {%n", descriptor.name());
+    private void printModuleInfo(PrintWriter writer, ModuleDescriptor md) {
+        writer.format("%smodule %s {%n", open ? "open " : "", md.name());
 
         Map<String, Module> modules = configuration.getModules();
         // first print the JDK modules
-        descriptor.requires().stream()
-                  .filter(req -> !req.name().equals("java.base"))   // implicit requires
-                  .sorted(Comparator.comparing(Requires::name))
-                  .forEach(req -> writer.format("    requires %s;%n", req));
+        md.requires().stream()
+          .filter(req -> !req.name().equals("java.base"))   // implicit requires
+          .sorted(Comparator.comparing(Requires::name))
+          .forEach(req -> writer.format("    requires %s;%n", req));
 
-        descriptor.exports().stream()
-                  .peek(exp -> {
-                      if (exp.targets().size() > 0)
-                          throw new InternalError(descriptor.name() + " qualified exports: " + exp);
-                  })
-                  .sorted(Comparator.comparing(Exports::source))
-                  .forEach(exp -> writer.format("    exports %s;%n", exp.source()));
+        if (!open) {
+            md.exports().stream()
+              .peek(exp -> {
+                 if (exp.targets().size() > 0)
+                    throw new InternalError(md.name() + " qualified exports: " + exp);
+              })
+              .sorted(Comparator.comparing(Exports::source))
+              .forEach(exp -> writer.format("    exports %s;%n", exp.source()));
+        }
 
-        descriptor.provides().values().stream()
-                    .sorted(Comparator.comparing(Provides::service))
-                    .forEach(p -> p.providers().stream()
-                        .sorted()
-                        .forEach(impl -> writer.format("    provides %s with %s;%n", p.service(), impl)));
+        md.provides().stream()
+          .sorted(Comparator.comparing(Provides::service))
+          .map(p -> p.providers().stream()
+                     .map(impl -> "        " + impl.replace('$', '.'))
+                     .collect(joining(",\n",
+                                      String.format("    provides %s with%n",
+                                                    p.service().replace('$', '.')),
+                                      ";")))
+          .forEach(writer::println);
 
         writer.println("}");
     }
 
-
     private Set<Module> automaticModules() {
         return automaticToExplicitModule.keySet();
     }
 
     /**
-     * Compute 'requires public' dependences by analyzing API dependencies
+     * Compute 'requires transitive' dependences by analyzing API dependencies
      */
-    private Map<Archive, Set<Archive>> computeRequiresPublic() throws IOException {
+    private Map<Archive, Set<Archive>> computeRequiresTransitive()
+        throws IOException
+    {
         // parse the input modules
         dependencyFinder.parseExportedAPIs(automaticModules().stream());
 
diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
index 8ff970e..994ebed 100644
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
@@ -125,6 +125,13 @@
 \  --generate-module-info <dir>  Generate module-info.java under the specified\n\
 \                                directory. The specified JAR files will be\n\
 \                                analyzed. This option cannot be used with\n\
+\                                --dot-output or --class-path. Use \n\
+\                                --generate-open-module option for open modules.
+
+main.opt.generate-open-module=\
+\  --generate-open-module <dir>  Generate module-info.java for the specified\n\
+\                                JAR files under the specified directory as\n\
+\                                open modules. This option cannot be used with\n\
 \                                --dot-output or --class-path.
 
 main.opt.check=\
diff --git a/langtools/src/jdk.jdeps/share/classes/module-info.java b/langtools/src/jdk.jdeps/share/classes/module-info.java
index 7c1240d..87e2135 100644
--- a/langtools/src/jdk.jdeps/share/classes/module-info.java
+++ b/langtools/src/jdk.jdeps/share/classes/module-info.java
@@ -33,9 +33,7 @@
     exports com.sun.tools.classfile to
         jdk.jlink;
 
-    provides java.util.spi.ToolProvider
-        with com.sun.tools.javap.Main.JavapToolProvider;
-
-    provides java.util.spi.ToolProvider
-        with com.sun.tools.jdeps.Main.JDepsToolProvider;
+    provides java.util.spi.ToolProvider with
+        com.sun.tools.javap.Main.JavapToolProvider,
+        com.sun.tools.jdeps.Main.JDepsToolProvider;
 }
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java
index e7c2ffd..6738ac2 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java
@@ -279,7 +279,7 @@
      */
     @Override
     public void hard(String format, Object... args) {
-        rawout(feedback.getPre() + format + feedback.getPost(), args);
+        rawout(prefix(format), args);
     }
 
     /**
@@ -289,7 +289,7 @@
      * @param args printf args
      */
     void error(String format, Object... args) {
-        rawout(feedback.getErrorPre() + format + feedback.getErrorPost(), args);
+        rawout(prefixError(format), args);
     }
 
     /**
@@ -315,18 +315,6 @@
     }
 
     /**
-     * Optional output -- with embedded per- and post-fix
-     *
-     * @param format printf format
-     * @param args printf args
-     */
-    void fluffRaw(String format, Object... args) {
-        if (showFluff()) {
-            rawout(format, args);
-        }
-    }
-
-    /**
      * Resource bundle look-up
      *
      * @param key the resource key
@@ -351,28 +339,42 @@
     }
 
     /**
-     * Add prefixing to embedded newlines in a string, leading with the normal
-     * prefix
+     * Add normal prefixing/postfixing to embedded newlines in a string,
+     * bracketing with normal prefix/postfix
      *
      * @param s the string to prefix
+     * @return the pre/post-fixed and bracketed string
      */
     String prefix(String s) {
-        return prefix(s, feedback.getPre());
+         return prefix(s, feedback.getPre(), feedback.getPost());
     }
 
     /**
-     * Add prefixing to embedded newlines in a string
+     * Add error prefixing/postfixing to embedded newlines in a string,
+     * bracketing with error prefix/postfix
      *
      * @param s the string to prefix
-     * @param leading the string to prepend
+     * @return the pre/post-fixed and bracketed string
      */
-    String prefix(String s, String leading) {
-        if (s == null || s.isEmpty()) {
+    String prefixError(String s) {
+         return prefix(s, feedback.getErrorPre(), feedback.getErrorPost());
+    }
+
+    /**
+     * Add prefixing/postfixing to embedded newlines in a string,
+     * bracketing with prefix/postfix
+     *
+     * @param s the string to prefix
+     * @param pre the string to prepend to each line
+     * @param post the string to append to each line (replacing newline)
+     * @return the pre/post-fixed and bracketed string
+     */
+    String prefix(String s, String pre, String post) {
+        if (s == null) {
             return "";
         }
-        return leading
-                + s.substring(0, s.length() - 1).replaceAll("\\R", System.getProperty("line.separator") + feedback.getPre())
-                + s.substring(s.length() - 1, s.length());
+        String pp = s.replaceAll("\\R", post + pre);
+        return pre + pp + post;
     }
 
     /**
@@ -381,8 +383,7 @@
      * @param key the resource key
      */
     void hardrb(String key) {
-        String s = prefix(getResourceString(key));
-        cmdout.println(s);
+        hard(getResourceString(key));
     }
 
     /**
@@ -405,7 +406,7 @@
      */
     @Override
     public void hardmsg(String key, Object... args) {
-        cmdout.println(prefix(messageFormat(key, args)));
+        hard(messageFormat(key, args));
     }
 
     /**
@@ -418,7 +419,7 @@
     @Override
     public void errormsg(String key, Object... args) {
         if (isRunningInteractive()) {
-            cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre()));
+            rawout(prefixError(messageFormat(key, args)));
         } else {
             startmsg(key, args);
         }
@@ -431,7 +432,7 @@
      * @param args
      */
     void startmsg(String key, Object... args) {
-        cmderr.println(prefix(messageFormat(key, args), ""));
+        cmderr.println(messageFormat(key, args));
     }
 
     /**
@@ -452,15 +453,9 @@
         Map<String, String> a2b = stream.collect(toMap(a, b,
                 (m1, m2) -> m1,
                 () -> new LinkedHashMap<>()));
-        int aLen = 0;
-        for (String av : a2b.keySet()) {
-            aLen = Math.max(aLen, av.length());
-        }
-        String format = "   %-" + aLen + "s -- %s";
-        String indentedNewLine = LINE_SEP + feedback.getPre()
-                + String.format("   %-" + (aLen + 4) + "s", "");
         for (Entry<String, String> e : a2b.entrySet()) {
-            hard(format, e.getKey(), e.getValue().replaceAll("\n", indentedNewLine));
+            hard("%s", e.getKey());
+            rawout(prefix(e.getValue(), feedback.getPre() + "\t", feedback.getPost()));
         }
     }
 
@@ -1096,6 +1091,7 @@
             }
             if (path.isEmpty()) {
                 StreamSupport.stream(FileSystems.getDefault().getRootDirectories().spliterator(), false)
+                             .filter(root -> Files.exists(root))
                              .filter(root -> accept.test(root) && root.toString().startsWith(prefix))
                              .map(root -> new ArgSuggestion(root.toString()))
                              .forEach(result::add);
@@ -1697,7 +1693,7 @@
         } else if (start.isEmpty()) {
             stset = cmd + "-none";
         } else {
-            stset = prefix("startup.jsh:\n" + start + "\n" + cmd + "startup.jsh", "");
+            stset = "startup.jsh:\n" + start + "\n" + cmd + "startup.jsh";
         }
         hard(stset);
     }
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties
index 0630af7..2ed00cc 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties
@@ -25,7 +25,7 @@
 
 jshell.msg.welcome =\
 Welcome to JShell -- Version {0}\n\
-For an introduction type: /help intro\n
+For an introduction type: /help intro
 jshell.err.opt.arg = Argument to {0} missing.
 jshell.err.opt.invalid = Invalid options: {0}.
 jshell.err.opt.one = Only one {0} option may be used.
@@ -94,7 +94,8 @@
 Type a Java language expression, statement, or declaration.\n\
 Or type one of the following commands:\n
 jshell.msg.help.subject =\n\
-For more information type ''/help'' followed by the name of command or a subject.\n\
+For more information type ''/help'' followed by the name of a\n\
+command or a subject.\n\
 For example ''/help /list'' or ''/help intro''.  Subjects:\n
 
 jshell.err.drop.arg =\
@@ -674,7 +675,7 @@
 \n\
 Where <mode> is the name of a previously defined feedback mode.\n\
 Where <prompt> and <continuation-prompt> are quoted strings printed as input prompts;\n\
-Both may optionally contain '%s' which will be substituted with the next snippet id --\n\
+Both may optionally contain '%%s' which will be substituted with the next snippet id --\n\
 note that what is entered may not be assigned that id, for example it may be an error or command.\n\
 The continuation-prompt is used on the second and subsequent lines of a multi-line snippet.\n\
 \n\
diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties
index b4d9335..055b044 100644
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties
@@ -126,7 +126,7 @@
 
 jshell.console.see.more = <\u8A73\u7D30\u306F\u3001\u30BF\u30D6\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044>
 jshell.console.do.nothing = \u4F55\u3082\u3057\u306A\u3044
-jshell.console.choice = \u9078\u629E: 
+jshell.console.choice = \u9078\u629E:
 jshell.console.create.variable = \u5909\u6570\u306E\u4F5C\u6210
 jshell.console.resolvable = \n\u8B58\u5225\u5B50\u306F\u3053\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3067\u89E3\u6C7A\u3067\u304D\u307E\u3059\u3002
 jshell.console.no.candidate = \n\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u5019\u88DC\u306E\u5B8C\u5168\u4FEE\u98FE\u3055\u308C\u305F\u540D\u524D\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
diff --git a/langtools/src/jdk.jshell/share/classes/module-info.java b/langtools/src/jdk.jshell/share/classes/module-info.java
index f8d8122..d77cad5 100644
--- a/langtools/src/jdk.jshell/share/classes/module-info.java
+++ b/langtools/src/jdk.jshell/share/classes/module-info.java
@@ -29,13 +29,13 @@
  * Read-Eval-Print Loops (REPLs).
  */
 module jdk.jshell {
-    requires public java.compiler;
+    requires transitive java.compiler;
+    requires transitive jdk.jdi;
     requires java.prefs;
     requires jdk.compiler;
     requires jdk.internal.le;
     requires jdk.internal.ed;
     requires jdk.internal.opt;
-    requires jdk.jdi;
 
     exports jdk.jshell;
     exports jdk.jshell.spi;
diff --git a/langtools/test/Makefile b/langtools/test/Makefile
index 47e9c2b..5a0a700 100644
--- a/langtools/test/Makefile
+++ b/langtools/test/Makefile
@@ -161,6 +161,9 @@
 JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx768m
 JTREG_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
 
+# Retain all files for failing tests
+JTREG_OPTIONS += -retain:fail,error
+
 ifdef EXTRA_JTREG_OPTIONS
   JTREG_OPTIONS += $(EXTRA_JTREG_OPTIONS)
 endif
@@ -211,7 +214,7 @@
 endif
 
 # Default verbosity setting for jtreg
-JTREG_VERBOSE ?= fail,error,nopass
+JTREG_VERBOSE ?= fail,error,time
 
 # Default verbosity setting for jck
 JCK_VERBOSE ?= non-pass
diff --git a/langtools/test/TEST.ROOT b/langtools/test/TEST.ROOT
index dc236a5..43aafad 100644
--- a/langtools/test/TEST.ROOT
+++ b/langtools/test/TEST.ROOT
@@ -14,8 +14,8 @@
 # Group definitions
 groups=TEST.groups
 
-# Tests using jtreg 4.2 b03 features
-requiredVersion=4.2 b03
+# Tests using jtreg 4.2 b04 features
+requiredVersion=4.2 b04
 
 # Use new module options
 useNewOptions=true
diff --git a/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java b/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java
index 9941796..a0ac819 100644
--- a/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java
+++ b/langtools/test/jdk/javadoc/doclet/testInterface/TestInterface.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      4682448 4947464 5029946 8025633 8026567 8035473
+ * @bug      4682448 4947464 5029946 8025633 8026567 8035473 8139101
  * @summary  Verify that the public modifier does not show up in the
  *           documentation for public methods, as recommended by the JLS.
  *           If A implements I and B extends A, B should be in the list of
@@ -121,6 +121,11 @@
         checkOutput("pkg/Interface.html", false,
                 "public int&nbsp;method()",
                 "public static final&nbsp;int field");
+
+        checkOutput("pkg/ClassWithStaticMethod.html", false,
+                //Make sure "Specified By" does not appear on class documentation when
+                //the method is a static method in the interface.
+                "<dt><span class=\"overrideSpecifyLabel\">Specified by:</span></dt>\n");
     }
 
     @Test
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/jdk/javadoc/doclet/testInterface/pkg/ClassWithStaticMethod.java
similarity index 87%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to langtools/test/jdk/javadoc/doclet/testInterface/pkg/ClassWithStaticMethod.java
index 242f168..db4e031 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/jdk/javadoc/doclet/testInterface/pkg/ClassWithStaticMethod.java
@@ -21,5 +21,11 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package pkg;
+
+public class ClassWithStaticMethod implements InterfaceWithStaticMethod {
+
+    public static void staticMethod() {
+    }
+
+}
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/langtools/test/jdk/javadoc/doclet/testInterface/pkg/InterfaceWithStaticMethod.java
similarity index 88%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to langtools/test/jdk/javadoc/doclet/testInterface/pkg/InterfaceWithStaticMethod.java
index 4c3b290..2442ce3 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/langtools/test/jdk/javadoc/doclet/testInterface/pkg/InterfaceWithStaticMethod.java
@@ -21,9 +21,12 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+package pkg;
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+public interface InterfaceWithStaticMethod {
+
+    /**
+     * A static method
+     */
+    static void staticMethod() { }
 }
diff --git a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
index 12703fa..d36d7e3 100644
--- a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363
+ * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363 8168766
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../lib
@@ -181,6 +181,34 @@
         checkModuleFilesAndLinks(true);
     }
 
+    /**
+     * Test generated module pages for a deprecated module.
+     */
+    @Test
+    void testModuleDeprecation() {
+        javadoc("-d", "out-moduledepr",
+                "-tag", "regular:a:Regular Tag:",
+                "-tag", "moduletag:s:Module Tag:",
+                "--module-source-path", testSrc,
+                "--module", "module1,module2,moduletags",
+                "testpkgmdl1", "testpkgmdl2", "testpkgmdltags");
+        checkExit(Exit.OK);
+        checkModuleDeprecation(true);
+    }
+
+    /**
+     * Test annotations on modules.
+     */
+    @Test
+    void testModuleAnnotation() {
+        javadoc("-d", "out-moduleanno",
+                "--module-source-path", testSrc,
+                "--module", "module1,module2",
+                "testpkgmdl1", "testpkgmdl2");
+        checkExit(Exit.OK);
+        checkModuleAnnotation();
+    }
+
     void checkDescription(boolean found) {
         checkOutput("module1-summary.html", found,
                 "<!-- ============ MODULE DESCRIPTION =========== -->\n"
@@ -218,6 +246,9 @@
     void checkHtml5Description(boolean found) {
         checkOutput("module1-summary.html", found,
                 "<section role=\"region\">\n"
+                + "<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
+                + "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated.</span></div>\n"
+                + "</div>\n"
                 + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
                 + "<a id=\"module.description\">\n"
                 + "<!--   -->\n"
@@ -556,4 +587,37 @@
                 + "<dd>&nbsp;</dd>\n"
                 + "</dl>");
 }
+
+    void checkModuleDeprecation(boolean found) {
+        checkOutput("module1-summary.html", found,
+                "<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
+                + "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated.</span></div>\n"
+                + "</div>");
+        checkOutput("deprecated-list.html", found,
+                "<ul>\n"
+                + "<li><a href=\"#module\">Deprecated Modules</a></li>\n"
+                + "</ul>",
+                "<tr class=\"altColor\">\n"
+                + "<th class=\"colFirst\" scope=\"row\"><a href=\"module1-summary.html\">module1</a></th>\n"
+                + "<td class=\"colLast\">\n"
+                + "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated.</span></div>\n"
+                + "</td>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", !found,
+                "<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span>\n"
+                + "<div class=\"block\"><span class=\"deprecationComment\">This module is deprecated using just the javadoc tag.</span></div>");
+        checkOutput("moduletags-summary.html", found,
+                "<p>@Deprecated\n"
+                + "</p>",
+                "<div class=\"deprecatedContent\"><span class=\"deprecatedLabel\">Deprecated.</span></div>");
+    }
+
+    void checkModuleAnnotation() {
+        checkOutput("module2-summary.html", true,
+                "<p><a href=\"testpkgmdl2/AnnotationType.html\" title=\"annotation in testpkgmdl2\">@AnnotationType</a>(<a href=\"testpkgmdl2/AnnotationType.html#optional--\">optional</a>=\"Module Annotation\",\n"
+                + "                <a href=\"testpkgmdl2/AnnotationType.html#required--\">required</a>=2016)\n"
+                + "</p>");
+        checkOutput("module2-summary.html", false,
+                "@AnnotationTypeUndocumented");
+}
 }
diff --git a/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java b/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java
index 90b3107..c5e1fba 100644
--- a/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java
@@ -25,7 +25,10 @@
 
 /**
   * This is a test description for the module1 module. Search phrase {@index "search phrase" with description}.
+  *
+  * @deprecated This module is deprecated.
   */
+@Deprecated
 module module1 {
     requires module2;
 
diff --git a/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java
index d499eda..fea478d 100644
--- a/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java
@@ -25,7 +25,11 @@
 
 /**
   * This is a test description for the module2 module. Search word {@index search_word} with no description.
+  *
+  * @deprecated This module is deprecated using just the javadoc tag.
   */
+@testpkgmdl2.AnnotationType(optional="Module Annotation", required=2016)
+@testpkgmdl2.AnnotationTypeUndocumented(optional="Module Annotation", required=2016)
 module module2 {
     exports testpkgmdl2;
 
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/AnnotationType.java
similarity index 74%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/AnnotationType.java
index 789cdb9..5a0a219 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/AnnotationType.java
@@ -21,13 +21,26 @@
  * questions.
  */
 
-package p7;
+package testpkgmdl2;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
-    }
+import java.lang.annotation.*;
+
+/**
+ * This is a test annotation type.
+ */
+@Documented public @interface AnnotationType {
+
+    /**
+     * The copyright holder.
+     *
+     * @return a string.
+     */
+    String optional() default "unknown";
+
+   /**
+    * The year of the copyright.
+    *
+    * @return an int.
+    */
+    int required();
 }
diff --git a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/AnnotationTypeUndocumented.java
similarity index 71%
copy from hotspot/test/serviceability/jdwp/JdwpCanReadReply.java
copy to langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/AnnotationTypeUndocumented.java
index 438f741..757e587 100644
--- a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/AnnotationTypeUndocumented.java
@@ -20,22 +20,28 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-import java.io.DataInputStream;
-import java.io.IOException;
+
+package testpkgmdl2;
+
+import java.lang.annotation.*;
 
 /**
- * The reply to the JDWP CANREAD command
+ * This is a test annotation type this is not documented because it
+ * is missing the @Documented tag.
  */
-public class JdwpCanReadReply extends JdwpReply {
+public @interface AnnotationTypeUndocumented {
 
-    private boolean canRead;
+    /**
+     * The copyright holder.
+     *
+     * @return a string.
+     */
+    String optional() default "unknown";
 
-    protected void parseData(DataInputStream ds) throws IOException {
-        canRead = (ds.read() != 0);
-    }
-
-    public boolean canRead() {
-        return canRead;
-    }
-
+   /**
+    * The year of the copyright.
+    *
+    * @return an int.
+    */
+    int required();
 }
diff --git a/langtools/test/jdk/javadoc/doclet/testModules/moduletags/module-info.java b/langtools/test/jdk/javadoc/doclet/testModules/moduletags/module-info.java
index 6265256..ecd3473 100644
--- a/langtools/test/jdk/javadoc/doclet/testModules/moduletags/module-info.java
+++ b/langtools/test/jdk/javadoc/doclet/testModules/moduletags/module-info.java
@@ -37,6 +37,7 @@
   * @moduletag Just a simple module tag.
   * @version 1.0
   */
+@Deprecated
 module moduletags {
     requires module2;
 
diff --git a/langtools/test/jdk/javadoc/tool/modules/Modules.java b/langtools/test/jdk/javadoc/tool/modules/Modules.java
index 39f94b6..2af3ba8 100644
--- a/langtools/test/jdk/javadoc/tool/modules/Modules.java
+++ b/langtools/test/jdk/javadoc/tool/modules/Modules.java
@@ -393,14 +393,14 @@
      * Module M : test module, with variable requires
      *
      * Module N :
-     *     requires public O  --->   Module O:
-     *                                 requires J   ---->   Module J:
-     *                                 exports openO          exports openJ
+     *     requires transitive O  --->   Module O:
+     *                                   requires J   ---->   Module J:
+     *                                   exports openO          exports openJ
      *
      *
      * Module L :
-     *     requires public P  --->   Module P:
-     *                                 exports openP
+     *     requires transitive P  --->   Module P:
+     *                                   exports openP
      *
      *
      */
@@ -431,14 +431,14 @@
     }
 
     @Test
-    public void testExpandRequiresPublic(Path base) throws Exception {
+    public void testExpandRequiresTransitive(Path base) throws Exception {
         Path src = base.resolve("src");
 
         createAuxiliaryModules(src);
 
         new ModuleBuilder(tb, "M")
                 .comment("The M module.")
-                .requiresPublic("N", src)
+                .requiresTransitive("N", src)
                 .requires("L", src)
                 .exports("p")
                 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
@@ -446,7 +446,7 @@
 
         execTask("--module-source-path", src.toString(),
                 "--module", "M",
-                "--expand-requires", "public");
+                "--expand-requires", "transitive");
 
         checkModulesSpecified("M", "N", "O");
         checkModulesIncluded("M", "N", "O");
@@ -462,7 +462,7 @@
 
         new ModuleBuilder(tb, "M")
                 .comment("The M module.")
-                .requiresPublic("N", src)
+                .requiresTransitive("N", src)
                 .requires("L", src)
                 .requires("O", src)
                 .exports("p")
@@ -490,7 +490,7 @@
 
         new ModuleBuilder(tb, "M")
                 .comment("The M module.")
-                .requiresPublic("N", src)
+                .requiresTransitive("N", src)
                 .requires("L", src)
                 .requires("O", src)
                 .exports("p")
@@ -512,7 +512,7 @@
 
         new ModuleBuilder(tb, "M")
                 .comment("The M module.")
-                .requiresPublic("N", src)
+                .requiresTransitive("N", src)
                 .requires("L", src)
                 .requires("O", src)
                 .exports("p")
@@ -538,7 +538,7 @@
         new ModuleBuilder(tb, "L")
                 .comment("The L module.")
                 .exports("openL")
-                .requiresPublic("P")
+                . requiresTransitive("P")
                 .classes("package openL; /** Class L open */ public class L { }")
                 .classes("package closedL;  /** Class L closed */ public class L { }")
                 .write(src);
@@ -546,7 +546,7 @@
         new ModuleBuilder(tb, "N")
                 .comment("The N module.")
                 .exports("openN")
-                .requiresPublic("O")
+                .requiresTransitive("O")
                 .classes("package openN; /** Class N open */ public class N  { }")
                 .classes("package closedN; /** Class N closed */ public class N { }")
                 .write(src);
diff --git a/langtools/test/jdk/jshell/CommandCompletionTest.java b/langtools/test/jdk/jshell/CommandCompletionTest.java
index f7d5034..5602f03 100644
--- a/langtools/test/jdk/jshell/CommandCompletionTest.java
+++ b/langtools/test/jdk/jshell/CommandCompletionTest.java
@@ -46,6 +46,7 @@
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import org.testng.annotations.Test;
 
@@ -144,7 +145,7 @@
         Compiler compiler = new Compiler();
         assertCompletion("/o|", false, "/open ");
         List<String> p1 = listFiles(Paths.get(""));
-        FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
+        getRootDirectories().forEach(s -> p1.add(s.toString()));
         Collections.sort(p1);
         assertCompletion("/open |", false, p1.toArray(new String[p1.size()]));
         Path classDir = compiler.getClassDir();
@@ -157,7 +158,7 @@
         assertCompletion("/s|", false, "/save ", "/set ");
         List<String> p1 = listFiles(Paths.get(""));
         Collections.addAll(p1, "-all ", "-history ", "-start ");
-        FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
+        getRootDirectories().forEach(s -> p1.add(s.toString()));
         Collections.sort(p1);
         assertCompletion("/save |", false, p1.toArray(new String[p1.size()]));
         Path classDir = compiler.getClassDir();
@@ -198,7 +199,7 @@
 
     public void testSet() throws IOException {
         List<String> p1 = listFiles(Paths.get(""));
-        FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
+        getRootDirectories().forEach(s -> p1.add(s.toString()));
         Collections.sort(p1);
 
         String[] modes = {"concise ", "normal ", "silent ", "verbose "};
@@ -267,4 +268,13 @@
                     (Files.isDirectory(file) ||
                      file.getFileName().toString().endsWith(".jar") ||
                      file.getFileName().toString().endsWith(".zip"));
+
+    private static Iterable<? extends Path> getRootDirectories() {
+        return StreamSupport.stream(FileSystems.getDefault()
+                                               .getRootDirectories()
+                                               .spliterator(),
+                                    false)
+                            .filter(p -> Files.exists(p))
+                            .collect(Collectors.toList());
+    }
 }
diff --git a/langtools/test/jdk/jshell/CompletionSuggestionTest.java b/langtools/test/jdk/jshell/CompletionSuggestionTest.java
index 8e355a1..6b068bc 100644
--- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java
+++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.java
@@ -29,6 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.javap
+ *          jdk.jshell/jdk.jshell:open
  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
  * @build KullaTesting TestingInputStream Compiler
  * @run testng CompletionSuggestionTest
diff --git a/langtools/test/jdk/jshell/ComputeFQNsTest.java b/langtools/test/jdk/jshell/ComputeFQNsTest.java
index 84b053a..5a82652 100644
--- a/langtools/test/jdk/jshell/ComputeFQNsTest.java
+++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java
@@ -28,6 +28,7 @@
  * @library /tools/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jshell/jdk.jshell:open
  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
  * @build KullaTesting TestingInputStream Compiler
  * @run testng ComputeFQNsTest
diff --git a/langtools/test/jdk/jshell/EditorTestBase.java b/langtools/test/jdk/jshell/EditorTestBase.java
index de81b7d..f611d64 100644
--- a/langtools/test/jdk/jshell/EditorTestBase.java
+++ b/langtools/test/jdk/jshell/EditorTestBase.java
@@ -253,7 +253,11 @@
                 a -> assertEditOutput(a, "/ed", "b ==> 10", () -> {
                     writeSource(getSource() + "\nint b = 10");
                     exit();
-                })
+                }),
+
+                //TODO: this is a work-around to JDK-8170369
+                a -> assertCommand(a, "1234",
+                        null, "", null, null, "")
         );
     }
 
diff --git a/langtools/test/jdk/jshell/ExternalEditorTest.java b/langtools/test/jdk/jshell/ExternalEditorTest.java
index ed5ef50..e38020e 100644
--- a/langtools/test/jdk/jshell/ExternalEditorTest.java
+++ b/langtools/test/jdk/jshell/ExternalEditorTest.java
@@ -24,7 +24,7 @@
 /*
  * @test
  * @summary Testing external editor.
- * @bug 8143955 8080843 8163816 8143006
+ * @bug 8143955 8080843 8163816 8143006 8169828
  * @modules jdk.jshell/jdk.internal.jshell.tool
  * @build ReplToolTesting CustomEditor EditorTestBase
  * @run testng ExternalEditorTest
diff --git a/langtools/test/jdk/jshell/HistoryTest.java b/langtools/test/jdk/jshell/HistoryTest.java
index 2dfc9a3..cbad5b2 100644
--- a/langtools/test/jdk/jshell/HistoryTest.java
+++ b/langtools/test/jdk/jshell/HistoryTest.java
@@ -26,7 +26,7 @@
  * @bug 8166744
  * @summary Test Completion
  * @modules jdk.internal.le/jdk.internal.jline.extra
- *          jdk.jshell/jdk.internal.jshell.tool
+ *          jdk.jshell/jdk.internal.jshell.tool:+open
  * @build HistoryTest
  * @run testng HistoryTest
  */
diff --git a/langtools/test/jdk/jshell/JavadocTest.java b/langtools/test/jdk/jshell/JavadocTest.java
index 816281f..a43ef91 100644
--- a/langtools/test/jdk/jshell/JavadocTest.java
+++ b/langtools/test/jdk/jshell/JavadocTest.java
@@ -28,7 +28,7 @@
  * @library /tools/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
- *          jdk.jshell
+ *          jdk.jshell/jdk.jshell:open
  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
  * @build KullaTesting TestingInputStream Compiler
  * @run testng JavadocTest
diff --git a/langtools/test/jdk/jshell/PipeInputStreamTest.java b/langtools/test/jdk/jshell/PipeInputStreamTest.java
index c062028..ba097b1 100644
--- a/langtools/test/jdk/jshell/PipeInputStreamTest.java
+++ b/langtools/test/jdk/jshell/PipeInputStreamTest.java
@@ -25,7 +25,7 @@
  * @test 8167461
  * @summary Verify PipeInputStream works.
  * @modules jdk.compiler/com.sun.tools.javac.util
- *          jdk.jshell
+ *          jdk.jshell/jdk.jshell.execution:open
  * @run testng PipeInputStreamTest
  */
 
diff --git a/langtools/test/jdk/jshell/ToolCommandOptionTest.java b/langtools/test/jdk/jshell/ToolCommandOptionTest.java
index e116c71..2f1182a 100644
--- a/langtools/test/jdk/jshell/ToolCommandOptionTest.java
+++ b/langtools/test/jdk/jshell/ToolCommandOptionTest.java
@@ -23,12 +23,16 @@
 
  /*
  * @test
- * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637
+ * @bug 8157395 8157393 8157517 8158738 8167128 8163840 8167637 8170368
  * @summary Tests of jshell comand options, and undoing operations
  * @modules jdk.jshell/jdk.internal.jshell.tool
+ *          jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @library /tools/lib
  * @build ToolCommandOptionTest ReplToolTesting
  * @run testng ToolCommandOptionTest
  */
+import java.nio.file.Path;
 import org.testng.annotations.Test;
 import static org.testng.Assert.assertFalse;
 
@@ -240,6 +244,9 @@
     }
 
     public void setStartTest() {
+        Compiler compiler = new Compiler();
+        Path startup = compiler.getPath("StartTest/startup.txt");
+        compiler.writeToFile(startup, "int iAmHere = 1234;");
         test(
                 (a) -> assertCommand(a, "/set start -furball",
                         "|  Unknown option: -furball -- /set start -furball"),
@@ -257,6 +264,13 @@
                         ""),
                 (a) -> assertCommand(a, "/set start",
                         "|  /set start -default"),
+                (a) -> assertCommand(a, "/set start " + startup.toString(),
+                        ""),
+                (a) -> assertCommand(a, "/set start",
+                        "|  startup.jsh:\n" +
+                        "|  int iAmHere = 1234;\n" +
+                        "|  \n" +
+                        "|  /set start startup.jsh"),
                 (a) -> assertCommand(a, "/se sta -no",
                         ""),
                 (a) -> assertCommand(a, "/set start",
@@ -265,6 +279,9 @@
     }
 
     public void retainStartTest() {
+        Compiler compiler = new Compiler();
+        Path startup = compiler.getPath("StartTest/startup.txt");
+        compiler.writeToFile(startup, "int iAmHere = 1234;");
         test(
                 (a) -> assertCommand(a, "/set start -retain -furball",
                         "|  Unknown option: -furball -- /set start -retain -furball"),
@@ -292,7 +309,14 @@
                 (a) -> assertCommand(a, "/se st -ret",
                         ""),
                 (a) -> assertCommand(a, "/se sta",
-                        "|  /set start -retain -none")
+                        "|  /set start -retain -none"),
+                (a) -> assertCommand(a, "/set start -retain " + startup.toString(),
+                        ""),
+                (a) -> assertCommand(a, "/set start",
+                        "|  startup.jsh:\n" +
+                        "|  int iAmHere = 1234;\n" +
+                        "|  \n" +
+                        "|  /set start -retain startup.jsh")
         );
     }
 
diff --git a/langtools/test/jdk/jshell/ToolSimpleTest.java b/langtools/test/jdk/jshell/ToolSimpleTest.java
index d97441d..6862d8f 100644
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -280,6 +280,16 @@
         );
     }
 
+    public void testApplicationOfPost() {
+        test(
+                (a) -> assertCommand(a, "/set mode t normal -command", "|  Created new feedback mode: t"),
+                (a) -> assertCommand(a, "/set feedback t", "|  Feedback mode: t"),
+                (a) -> assertCommand(a, "/set format t post \"$%n\"", ""),
+                (a) -> assertCommand(a, "/set prompt t \"+\" \"-\"", ""),
+                (a) -> assertCommand(a, "/set prompt t", "|  /set prompt t \"+\" \"-\"$")
+        );
+    }
+
     public void testHelpLength() {
         Consumer<String> testOutput = (s) -> {
             List<String> ss = Stream.of(s.split("\n"))
@@ -300,14 +310,35 @@
                 (a) -> assertHelp(a, "/help", "/list", "/help", "/exit", "intro"),
                 (a) -> assertHelp(a, "/help short", "shortcuts", "<tab>"),
                 (a) -> assertHelp(a, "/? /li", "/list -all", "snippets"),
+                (a) -> assertHelp(a, "/help /set prompt", "optionally contain '%s'", "quoted"),
                 (a) -> assertHelp(a, "/help /help", "/help <command>")
         );
     }
 
+    public void testHelpFormat() {
+        test(
+                (a) -> assertCommandCheckOutput(a, "/help", s -> {
+                    String[] lines = s.split("\\R");
+                    assertTrue(lines.length > 20,
+                            "Too few lines of /help output: " + lines.length
+                          + "\n" + s);
+                    for (int i = 0; i < lines.length; ++i) {
+                        String l = lines[i];
+                        assertTrue(l.startsWith("| "),
+                                "Expected /help line to start with | :\n" + l);
+                        assertTrue(l.length() <= 80,
+                                "/help line too long: " + l.length() + "\n" + l);
+                    }
+                 })
+        );
+    }
+
     private void assertHelp(boolean a, String command, String... find) {
         assertCommandCheckOutput(a, command, s -> {
             for (String f : find) {
-                assertTrue(s.contains(f), "Expected output of " + command + " to contain: " + f);
+                assertTrue(s.contains(f),
+                        "Expected output of " + command + " to contain: " + f
+                      + "\n" + s);
             }
         });
     }
diff --git a/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java b/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java
index 4a8ccea..480e380 100644
--- a/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java
+++ b/langtools/test/lib/annotations/annotations/classfile/ClassfileInspector.java
@@ -1188,7 +1188,7 @@
         }
 
         @Override
-        public Void visitConcealedPackages(ConcealedPackages_attribute attr, T p) {
+        public Void visitModulePackages(ModulePackages_attribute attr, T p) {
             return null;
         }
 
@@ -1238,7 +1238,7 @@
         }
 
         @Override
-        public Void visitHashes(Hashes_attribute attr, T p) {
+        public Void visitModuleHashes(ModuleHashes_attribute attr, T p) {
             return null;
         }
 
@@ -1263,7 +1263,7 @@
         }
 
         @Override
-        public Void visitMainClass(MainClass_attribute attr, T p) {
+        public Void visitModuleMainClass(ModuleMainClass_attribute attr, T p) {
             return null;
         }
 
@@ -1343,12 +1343,12 @@
         }
 
         @Override
-        public Void visitTargetPlatform(TargetPlatform_attribute attr, T p) {
+        public Void visitModuleTarget(ModuleTarget_attribute attr, T p) {
             return null;
         }
 
         @Override
-        public Void visitVersion(Version_attribute attr, T p) {
+        public Void visitModuleVersion(ModuleVersion_attribute attr, T p) {
             return null;
         }
 
diff --git a/langtools/test/tools/javac/6304921/TestLog.java b/langtools/test/tools/javac/6304921/TestLog.java
index 4c245dc..a2c2dfb 100644
--- a/langtools/test/tools/javac/6304921/TestLog.java
+++ b/langtools/test/tools/javac/6304921/TestLog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.parser
  *          jdk.compiler/com.sun.tools.javac.tree
- *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.compiler/com.sun.tools.javac.util:+open
  */
 import java.lang.reflect.Field;
 import java.io.InputStream;
diff --git a/langtools/test/tools/javac/6410653/T6410653.java b/langtools/test/tools/javac/6410653/T6410653.java
index d2ee3a4..338b77f 100644
--- a/langtools/test/tools/javac/6410653/T6410653.java
+++ b/langtools/test/tools/javac/6410653/T6410653.java
@@ -27,7 +27,7 @@
  * @summary REGRESSION: javac crashes if -d or -s argument is a file
  * @author  Peter von der Ah\u00e9
  * @modules java.compiler
- *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.compiler/com.sun.tools.javac.util:open
  */
 
 import java.lang.reflect.Field;
diff --git a/langtools/test/tools/javac/MethodParameters/AnnotationTest.java b/langtools/test/tools/javac/MethodParameters/AnnotationTest.java
index 2505ddb..68ef14f 100644
--- a/langtools/test/tools/javac/MethodParameters/AnnotationTest.java
+++ b/langtools/test/tools/javac/MethodParameters/AnnotationTest.java
@@ -26,7 +26,7 @@
  * @bug 8006582
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters AnnotationTest.java
  * @run main MethodParametersTester AnnotationTest AnnotationTest.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/AnonymousClass.java b/langtools/test/tools/javac/MethodParameters/AnonymousClass.java
index f76bd11..42acefe 100644
--- a/langtools/test/tools/javac/MethodParameters/AnonymousClass.java
+++ b/langtools/test/tools/javac/MethodParameters/AnonymousClass.java
@@ -26,7 +26,7 @@
  * @bug 8006582
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters AnonymousClass.java
  * @run main MethodParametersTester AnonymousClass AnonymousClass.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java b/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java
index f189fe3..85e6f10 100644
--- a/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java
+++ b/langtools/test/tools/javac/MethodParameters/AttributeVisitor.java
@@ -34,19 +34,21 @@
     public R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p) { return null; }
     public R visitCode(Code_attribute attr, P p) { return null; }
     public R visitCompilationID(CompilationID_attribute attr, P p) { return null; }
-    public R visitConcealedPackages(ConcealedPackages_attribute attr, P p) { return null; }
     public R visitConstantValue(ConstantValue_attribute attr, P p) { return null; }
     public R visitDeprecated(Deprecated_attribute attr, P p) { return null; }
     public R visitEnclosingMethod(EnclosingMethod_attribute attr, P p) { return null; }
     public R visitExceptions(Exceptions_attribute attr, P p) { return null; }
-    public R visitHashes(Hashes_attribute attr, P p) { return null; }
     public R visitInnerClasses(InnerClasses_attribute attr, P p) { return null; }
     public R visitLineNumberTable(LineNumberTable_attribute attr, P p) { return null; }
     public R visitLocalVariableTable(LocalVariableTable_attribute attr, P p) { return null; }
     public R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p) { return null; }
-    public R visitMainClass(MainClass_attribute attr, P p) { return null; }
     public R visitMethodParameters(MethodParameters_attribute attr, P p) { return null; }
     public R visitModule(Module_attribute attr, P p) { return null; }
+    public R visitModuleHashes(ModuleHashes_attribute attr, P p) { return null; }
+    public R visitModuleMainClass(ModuleMainClass_attribute attr, P p) { return null; }
+    public R visitModulePackages(ModulePackages_attribute attr, P p) { return null; }
+    public R visitModuleTarget(ModuleTarget_attribute attr, P p) { return null; }
+    public R visitModuleVersion(ModuleVersion_attribute attr, P p) { return null; }
     public R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p) { return null; }
     public R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p) { return null; }
     public R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p) { return null; }
@@ -60,6 +62,4 @@
     public R visitStackMap(StackMap_attribute attr, P p) { return null; }
     public R visitStackMapTable(StackMapTable_attribute attr, P p) { return null; }
     public R visitSynthetic(Synthetic_attribute attr, P p) { return null; }
-    public R visitTargetPlatform(TargetPlatform_attribute attr, P p) { return null; }
-    public R visitVersion(Version_attribute attr, P p) { return null; }
 }
diff --git a/langtools/test/tools/javac/MethodParameters/Constructors.java b/langtools/test/tools/javac/MethodParameters/Constructors.java
index 02b360e..b7629ce 100644
--- a/langtools/test/tools/javac/MethodParameters/Constructors.java
+++ b/langtools/test/tools/javac/MethodParameters/Constructors.java
@@ -26,7 +26,7 @@
  * @bug 8006582
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters Constructors.java
  * @run main MethodParametersTester Constructors Constructors.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/EnumTest.java b/langtools/test/tools/javac/MethodParameters/EnumTest.java
index 7ff3739..3c7bdd6 100644
--- a/langtools/test/tools/javac/MethodParameters/EnumTest.java
+++ b/langtools/test/tools/javac/MethodParameters/EnumTest.java
@@ -26,7 +26,7 @@
  * @bug 8006582 8008658
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters EnumTest.java
  * @run main MethodParametersTester EnumTest EnumTest.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/InstanceMethods.java b/langtools/test/tools/javac/MethodParameters/InstanceMethods.java
index 8da1cb6..980cee3 100644
--- a/langtools/test/tools/javac/MethodParameters/InstanceMethods.java
+++ b/langtools/test/tools/javac/MethodParameters/InstanceMethods.java
@@ -26,7 +26,7 @@
  * @bug 8006582
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters InstanceMethods.java
  * @run main MethodParametersTester InstanceMethods InstanceMethods.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/LambdaTest.java b/langtools/test/tools/javac/MethodParameters/LambdaTest.java
index 0fb92b6..66ec67c 100644
--- a/langtools/test/tools/javac/MethodParameters/LambdaTest.java
+++ b/langtools/test/tools/javac/MethodParameters/LambdaTest.java
@@ -26,7 +26,7 @@
  * @bug 8006582 8037546 8138729
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters LambdaTest.java
  * @run main MethodParametersTester LambdaTest LambdaTest.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/LocalClassTest.java b/langtools/test/tools/javac/MethodParameters/LocalClassTest.java
index 593daea..21d141f 100644
--- a/langtools/test/tools/javac/MethodParameters/LocalClassTest.java
+++ b/langtools/test/tools/javac/MethodParameters/LocalClassTest.java
@@ -26,7 +26,7 @@
  * @bug 8006582 8008658
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters LocalClassTest.java
  * @run main MethodParametersTester LocalClassTest LocalClassTest.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/MemberClassTest.java b/langtools/test/tools/javac/MethodParameters/MemberClassTest.java
index a2caf36..04e3cf7 100644
--- a/langtools/test/tools/javac/MethodParameters/MemberClassTest.java
+++ b/langtools/test/tools/javac/MethodParameters/MemberClassTest.java
@@ -26,7 +26,7 @@
  * @bug 8006582 8008658
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters MemberClassTest.java
  * @run main MethodParametersTester MemberClassTest MemberClassTest.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/StaticMethods.java b/langtools/test/tools/javac/MethodParameters/StaticMethods.java
index 9848bcc..186d6b5 100644
--- a/langtools/test/tools/javac/MethodParameters/StaticMethods.java
+++ b/langtools/test/tools/javac/MethodParameters/StaticMethods.java
@@ -26,7 +26,7 @@
  * @bug 8006582
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters StaticMethods.java
  * @run main MethodParametersTester StaticMethods StaticMethods.out
  */
diff --git a/langtools/test/tools/javac/MethodParameters/UncommonParamNames.java b/langtools/test/tools/javac/MethodParameters/UncommonParamNames.java
index 445d774..ab6dbc3 100644
--- a/langtools/test/tools/javac/MethodParameters/UncommonParamNames.java
+++ b/langtools/test/tools/javac/MethodParameters/UncommonParamNames.java
@@ -26,7 +26,7 @@
  * @bug 8006582
  * @summary javac should generate method parameters correctly.
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @build MethodParametersTester
+ * @build MethodParametersTester ClassFileVisitor ReflectionVisitor
  * @compile -parameters UncommonParamNames.java
  * @run main MethodParametersTester UncommonParamNames UncommonParamNames.out
  */
diff --git a/langtools/test/tools/javac/T6435291/T6435291.java b/langtools/test/tools/javac/T6435291/T6435291.java
index 85a3345..3bd6098 100644
--- a/langtools/test/tools/javac/T6435291/T6435291.java
+++ b/langtools/test/tools/javac/T6435291/T6435291.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/test/tools/javac/api/6400303/T6400303.java b/langtools/test/tools/javac/api/6400303/T6400303.java
index 3b86673..4feeb99 100644
--- a/langtools/test/tools/javac/api/6400303/T6400303.java
+++ b/langtools/test/tools/javac/api/6400303/T6400303.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/test/tools/javac/api/TestResolveIdent.java b/langtools/test/tools/javac/api/TestResolveIdent.java
index bb0fd0b..c72f652 100644
--- a/langtools/test/tools/javac/api/TestResolveIdent.java
+++ b/langtools/test/tools/javac/api/TestResolveIdent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java
index a5a8f84..fca688a 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTest.java
@@ -24,8 +24,9 @@
 /*
  * @test
  * @summary Module attribute tests
- * @bug 8080878
- * @modules jdk.compiler/com.sun.tools.javac.api
+ * @bug 8080878 8161906 8162713
+ * @modules java.compiler
+ *          jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.util
  *          jdk.jdeps/com.sun.tools.classfile
@@ -56,7 +57,7 @@
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .exports("pack")
                 .write(base);
-        tb.writeJavaFiles(base, "package pack; public class C extends java.util.ArrayList{}");
+        tb.writeJavaFiles(base, "package pack; public class C extends java.util.ArrayList{ }");
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
     }
@@ -67,11 +68,15 @@
                 .exports("pack")
                 .exports("pack2")
                 .exports("pack3")
+                .exports("pack4")
+                .exports("pack5")
                 .write(base);
         tb.writeJavaFiles(base,
-                "package pack; public class A {}",
-                "package pack2; public class B {}",
-                "package pack3; public class C {}");
+                "package pack; public class A { }",
+                "package pack2; public class B { }",
+                "package pack3; public class C { }",
+                "package pack4; public class C { }",
+                "package pack5; public class C { }");
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
     }
@@ -81,7 +86,17 @@
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .exportsTo("pack", "jdk.compiler")
                 .write(base);
-        tb.writeJavaFiles(base, "package pack; public class A {}");
+        tb.writeJavaFiles(base, "package pack; public class A { }");
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testQualifiedDynamicExports(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .exportsTo("pack", "jdk.compiler")
+                .write(base);
+        tb.writeJavaFiles(base, "package pack; public class A { }");
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
     }
@@ -89,14 +104,18 @@
     @Test
     public void testSeveralQualifiedExports(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .exportsTo("pack", "jdk.compiler, java.xml")
-                .exportsTo("pack2", "java.xml")
+                .exportsTo("pack", "jdk.compiler, jdk.jdeps")
+                .exportsTo("pack2", "jdk.jdeps")
                 .exportsTo("pack3", "jdk.compiler")
+                .exportsTo("pack4", "jdk.compiler, jdk.jdeps")
+                .exportsTo("pack5", "jdk.compiler")
                 .write(base);
         tb.writeJavaFiles(base,
                 "package pack; public class A {}",
                 "package pack2; public class B {}",
-                "package pack3; public class C {}");
+                "package pack3; public class C {}",
+                "package pack4; public class C {}",
+                "package pack5; public class C {}");
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
     }
@@ -111,9 +130,18 @@
     }
 
     @Test
-    public void testRequiresPublic(Path base) throws Exception {
+    public void testRequiresTransitive(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .requiresPublic("java.xml")
+                .requires("jdk.jdeps", RequiresFlag.TRANSITIVE)
+                .write(base);
+        compile(base);
+        testModuleAttribute(base, moduleDescriptor);
+    }
+
+    @Test
+    public void testRequiresStatic(Path base) throws Exception {
+        ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
+                .requires("jdk.jdeps", RequiresFlag.STATIC)
                 .write(base);
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
@@ -122,13 +150,20 @@
     @Test
     public void testSeveralRequires(Path base) throws Exception {
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
-                .requiresPublic("java.xml")
-                .requires("java.compiler")
+                .requires("jdk.jdeps", RequiresFlag.TRANSITIVE)
                 .requires("jdk.compiler")
-                .requiresPublic("jdk.scripting.nashorn")
-                .write(base);
-        compile(base);
-        testModuleAttribute(base, moduleDescriptor);
+                .requires("m2", RequiresFlag.STATIC)
+                .requires("m3")
+                .requires("m4", RequiresFlag.TRANSITIVE)
+                .requires("m5", RequiresFlag.STATIC, RequiresFlag.TRANSITIVE)
+                .write(base.resolve("m1"));
+        tb.writeJavaFiles(base.resolve("m2"), "module m2 { }");
+        tb.writeJavaFiles(base.resolve("m3"), "module m3 { }");
+        tb.writeJavaFiles(base.resolve("m4"), "module m4 { }");
+        tb.writeJavaFiles(base.resolve("m5"), "module m5 { }");
+        compile(base, "--module-source-path", base.toString(),
+                "-d", base.toString());
+        testModuleAttribute(base.resolve("m1"), moduleDescriptor);
     }
 
     @Test
@@ -136,7 +171,7 @@
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .provides("java.util.Collection", "pack2.D")
                 .write(base);
-        tb.writeJavaFiles(base, "package pack2; public class D extends java.util.ArrayList{}");
+        tb.writeJavaFiles(base, "package pack2; public class D extends java.util.ArrayList{ }");
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
     }
@@ -146,15 +181,11 @@
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .provides("java.util.Collection", "pack2.D")
                 .provides("java.util.List", "pack2.D")
-                .requires("java.logging")
-                .provides("java.util.logging.Logger", "pack2.C")
+                .requires("jdk.compiler")
+                .provides("com.sun.tools.javac.Main", "pack2.C")
                 .write(base);
-        tb.writeJavaFiles(base, "package pack2; public class D extends java.util.ArrayList{}",
-                "package pack2; public class C extends java.util.logging.Logger{ " +
-                        "public C() { super(\"\",\"\"); } \n" +
-                        "C(String a,String b){" +
-                        "    super(a,b);" +
-                        "}}");
+        tb.writeJavaFiles(base, "package pack2; public class D extends java.util.ArrayList{ }",
+                "package pack2; public class C extends com.sun.tools.javac.Main{ }");
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
     }
@@ -173,8 +204,8 @@
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .uses("java.util.List")
                 .uses("java.util.Collection")
-                .requires("java.logging")
-                .uses("java.util.logging.Logger")
+                .requires("jdk.compiler")
+                .uses("javax.tools.JavaCompiler")
                 .write(base);
         compile(base);
         testModuleAttribute(base, moduleDescriptor);
@@ -182,26 +213,44 @@
 
     @Test
     public void testComplex(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
         ModuleDescriptor moduleDescriptor = new ModuleDescriptor("m1")
                 .exports("pack1")
-                .exportsTo("packTo1", "java.xml")
+                .exports("pack3")
+                .exportsTo("packTo1", "m2")
+                .exportsTo("packTo3", "m3")
                 .requires("jdk.compiler")
-                .requiresPublic("java.xml")
-                .provides("java.util.List", "pack1.C")
+                .requires("m2", RequiresFlag.TRANSITIVE)
+                .requires("m3", RequiresFlag.STATIC)
+                .requires("m4", RequiresFlag.TRANSITIVE, RequiresFlag.STATIC)
+                .provides("java.util.List", "pack1.C", "pack2.D")
                 .uses("java.util.List")
                 .uses("java.nio.file.Path")
-                .provides("java.util.List", "pack2.D")
-                .requiresPublic("java.desktop")
+                .requires("jdk.jdeps", RequiresFlag.STATIC, RequiresFlag.TRANSITIVE)
+                .requires("m5", RequiresFlag.STATIC)
+                .requires("m6", RequiresFlag.TRANSITIVE)
                 .requires("java.compiler")
+                .exportsTo("packTo4", "java.compiler")
                 .exportsTo("packTo2", "java.compiler")
+                .exports("pack4")
                 .exports("pack2")
-                .write(base);
-        tb.writeJavaFiles(base, "package pack1; public class C extends java.util.ArrayList{}",
-                "package pack2; public class D extends java.util.ArrayList{}");
-        tb.writeJavaFiles(base,
+                .write(m1);
+        tb.writeJavaFiles(m1, "package pack1; public class C extends java.util.ArrayList{ }",
+                "package pack2; public class D extends java.util.ArrayList{ }",
+                "package pack3; public class D extends java.util.ArrayList{ }",
+                "package pack4; public class D extends java.util.ArrayList{ }");
+        tb.writeJavaFiles(m1,
                 "package packTo1; public class T1 {}",
-                "package packTo2; public class T2 {}");
-        compile(base);
-        testModuleAttribute(base, moduleDescriptor);
+                "package packTo2; public class T2 {}",
+                "package packTo3; public class T3 {}",
+                "package packTo4; public class T4 {}");
+        tb.writeJavaFiles(base.resolve("m2"), "module m2 { }");
+        tb.writeJavaFiles(base.resolve("m3"), "module m3 { }");
+        tb.writeJavaFiles(base.resolve("m4"), "module m4 { }");
+        tb.writeJavaFiles(base.resolve("m5"), "module m5 { }");
+        tb.writeJavaFiles(base.resolve("m6"), "module m6 { }");
+        compile(base, "--module-source-path", base.toString(),
+                "-d", base.toString());
+        testModuleAttribute(m1, moduleDescriptor);
     }
 }
diff --git a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java
index b48942d..9762afd 100644
--- a/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java
+++ b/langtools/test/tools/javac/classfiles/attributes/Module/ModuleTestBase.java
@@ -38,6 +38,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
@@ -86,7 +87,8 @@
         List<Pair<String, Integer>> actualRequires = new ArrayList<>();
         for (Module_attribute.RequiresEntry require : module.requires) {
             actualRequires.add(Pair.of(
-                    require.getRequires(constantPool), require.requires_flags));
+                    require.getRequires(constantPool).replace('/', '.'),
+                    require.requires_flags));
         }
         tr.checkContains(actualRequires, moduleDescriptor.requires, "Lists of requires don't match");
     }
@@ -96,11 +98,13 @@
         for (Module_attribute.ExportsEntry export : module.exports) {
             String pkg = constantPool.getUTF8Value(export.exports_index);
             if (tr.checkTrue(moduleDescriptor.exports.containsKey(pkg), "Unexpected export " + pkg)) {
-                List<String> expectedTo = moduleDescriptor.exports.get(pkg);
+                Export expectedExport = moduleDescriptor.exports.get(pkg);
+                tr.checkEquals(expectedExport.mask, export.exports_flags, "Wrong export flags");
+                List<String> expectedTo = expectedExport.to;
                 tr.checkEquals(export.exports_to_count, expectedTo.size(), "Wrong amount of exports to");
                 List<String> actualTo = new ArrayList<>();
                 for (int toIdx : export.exports_to_index) {
-                    actualTo.add(constantPool.getUTF8Value(toIdx));
+                    actualTo.add(constantPool.getUTF8Value(toIdx).replace('/', '.'));
                 }
                 tr.checkContains(actualTo, expectedTo, "Lists of \"exports to\" don't match.");
             }
@@ -118,14 +122,24 @@
     }
 
     private void testProvides(ModuleDescriptor moduleDescriptor, Module_attribute module, ConstantPool constantPool) throws ConstantPoolException {
-        tr.checkEquals(module.provides_count, moduleDescriptor.provides.size(), "Wrong amount of provides.");
-        List<Pair<String, String>> actualProvides = new ArrayList<>();
+        int moduleProvidesCount = Arrays.asList(module.provides).stream()
+                .mapToInt(e -> e.with_index.length)
+                .sum();
+        int moduleDescriptorProvidesCount = moduleDescriptor.provides.values().stream()
+                .mapToInt(impls -> impls.size())
+                .sum();
+        tr.checkEquals(moduleProvidesCount, moduleDescriptorProvidesCount, "Wrong amount of provides.");
+        Map<String, List<String>> actualProvides = new HashMap<>();
         for (Module_attribute.ProvidesEntry provide : module.provides) {
             String provides = constantPool.getClassInfo(provide.provides_index).getBaseName().replace('/', '.');
-            String with = constantPool.getClassInfo(provide.with_index).getBaseName().replace('/', '.');
-            actualProvides.add(Pair.of(provides, with));
+            List<String> impls = new ArrayList<>();
+            for (int i = 0; i < provide.with_count; i++) {
+                String with = constantPool.getClassInfo(provide.with_index[i]).getBaseName().replace('/', '.');
+                impls.add(with);
+            }
+            actualProvides.put(provides, impls);
         }
-        tr.checkContains(actualProvides, moduleDescriptor.provides, "Lists of provides don't match");
+        tr.checkContains(actualProvides.entrySet(), moduleDescriptor.provides.entrySet(), "Lists of provides don't match");
     }
 
     protected void compile(Path base, String... options) throws IOException {
@@ -145,7 +159,57 @@
     @interface Test {
     }
 
-    class ModuleDescriptor {
+    interface Mask {
+        int getMask();
+    }
+
+    public enum RequiresFlag implements Mask {
+        TRANSITIVE("transitive", Module_attribute.ACC_TRANSITIVE),
+        STATIC("static", Module_attribute.ACC_STATIC_PHASE);
+
+        private final String token;
+        private final int mask;
+
+        RequiresFlag(String token, int mask) {
+            this.token = token;
+            this.mask = mask;
+        }
+
+        @Override
+        public int getMask() {
+            return mask;
+        }
+    }
+
+    public enum ExportFlag implements Mask {
+        SYNTHETIC("", Module_attribute.ACC_SYNTHETIC);
+
+        private final String token;
+        private final int mask;
+
+        ExportFlag(String token, int mask) {
+            this.token = token;
+            this.mask = mask;
+        }
+
+        @Override
+        public int getMask() {
+            return mask;
+        }
+    }
+
+    private class Export {
+        String pkg;
+        int mask;
+        List<String> to = new ArrayList<>();
+
+        public Export(String pkg, int mask) {
+            this.pkg = pkg;
+            this.mask = mask;
+        }
+    }
+
+    protected class ModuleDescriptor {
 
         private final String name;
         //pair is name of module and flag(public,mandated,synthetic)
@@ -155,10 +219,10 @@
             requires.add(new Pair<>("java.base", Module_attribute.ACC_MANDATED));
         }
 
-        private final Map<String, List<String>> exports = new HashMap<>();
+        private final Map<String, Export> exports = new HashMap<>();
 
         //List of service and implementation
-        private final List<Pair<String, String>> provides = new ArrayList<>();
+        private final Map<String, List<String>> provides = new LinkedHashMap<>();
         private final List<String> uses = new ArrayList<>();
 
         private static final String LINE_END = ";\n";
@@ -170,43 +234,58 @@
             content.append(name).append('{').append('\n');
         }
 
-        public ModuleDescriptor requires(String... requires) {
-            for (String require : requires) {
-                this.requires.add(Pair.of(require, 0));
-                content.append("    requires ").append(require).append(LINE_END);
-            }
+        public ModuleDescriptor requires(String module) {
+            this.requires.add(Pair.of(module, 0));
+            content.append("    requires ").append(module).append(LINE_END);
+
             return this;
         }
 
-        public ModuleDescriptor requiresPublic(String... requiresPublic) {
-            for (String require : requiresPublic) {
-                this.requires.add(new Pair<>(require, Module_attribute.ACC_PUBLIC));
-                content.append("    requires public ").append(require).append(LINE_END);
+        public ModuleDescriptor requires(String module, RequiresFlag... flags) {
+            this.requires.add(new Pair<>(module, computeMask(flags)));
+
+            content.append("    requires ");
+            for (RequiresFlag flag : flags) {
+                content.append(flag.token).append(" ");
             }
+            content.append(module).append(LINE_END);
+
             return this;
         }
 
-        public ModuleDescriptor exports(String... exports) {
-            for (String export : exports) {
-                this.exports.putIfAbsent(export, new ArrayList<>());
-                content.append("    exports ").append(export).append(LINE_END);
+        public ModuleDescriptor exports(String pkg, ExportFlag... flags) {
+            this.exports.putIfAbsent(pkg, new Export(pkg, computeMask(flags)));
+            content.append("    exports ");
+            for (ExportFlag flag : flags) {
+                content.append(flag.token).append(" ");
             }
+            content.append(pkg).append(LINE_END);
             return this;
         }
 
-        public ModuleDescriptor exportsTo(String exports, String to) {
+        public ModuleDescriptor exportsTo(String pkg, String to, ExportFlag... flags) {
             List<String> tos = Pattern.compile(",")
                     .splitAsStream(to)
                     .map(String::trim)
                     .collect(Collectors.toList());
-            this.exports.computeIfAbsent(exports, k -> new ArrayList<>()).addAll(tos);
-            content.append("    exports ").append(exports).append(" to ").append(to).append(LINE_END);
+            this.exports.computeIfAbsent(pkg, k -> new Export(pkg, computeMask(flags)))
+                    .to.addAll(tos);
+
+            content.append("    exports ");
+            for (ExportFlag flag : flags) {
+                content.append(flag.token).append(" ");
+            }
+            content.append(pkg).append(" to ").append(to).append(LINE_END);
             return this;
         }
 
-        public ModuleDescriptor provides(String provides, String with) {
-            this.provides.add(Pair.of(provides, with));
-            content.append("    provides ").append(provides).append(" with ").append(with).append(LINE_END);
+        public ModuleDescriptor provides(String provides, String... with) {
+            this.provides.put(provides, Arrays.asList(with));
+            content.append("    provides ")
+                    .append(provides)
+                    .append(" with ")
+                    .append(String.join(",", with))
+                    .append(LINE_END);
             return this;
         }
 
@@ -225,5 +304,12 @@
             tb.writeJavaFiles(path, src);
             return this;
         }
+
+        private int computeMask(Mask[] masks) {
+            return Arrays.stream(masks)
+                    .map(Mask::getMask)
+                    .reduce((a, b) -> a | b)
+                    .orElseGet(() -> 0);
+        }
     }
 }
diff --git a/langtools/test/tools/javac/defaultMethods/BadClassfile.java b/langtools/test/tools/javac/defaultMethods/BadClassfile.java
index b7db500..9633ef3 100644
--- a/langtools/test/tools/javac/defaultMethods/BadClassfile.java
+++ b/langtools/test/tools/javac/defaultMethods/BadClassfile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt
index a201876..f13f1e7 100644
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt
@@ -69,6 +69,8 @@
 compiler.misc.module.name.mismatch
 compiler.misc.no.unique.minimal.instance.exists
 compiler.misc.no.unique.maximal.instance.exists         # cannot happen?
+compiler.err.module.non.zero.opens                      # bad class file
+compiler.misc.module.non.zero.opens                     # bad class file
 compiler.misc.resume.abort                              # prompt for a response
 compiler.misc.source.unavailable                        # DiagnosticSource
 compiler.misc.token.bad-symbol
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/tools/javac/diags/examples/AddOpensIgnored.java
similarity index 84%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to langtools/test/tools/javac/diags/examples/AddOpensIgnored.java
index 242f168..839e743 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/tools/javac/diags/examples/AddOpensIgnored.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,5 +21,8 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+// key: compiler.warn.addopens.ignored
+// options: --add-opens anything
+
+class Dummy { }
+
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java b/langtools/test/tools/javac/diags/examples/ConflictingExports/exported/Class.java
similarity index 100%
rename from langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java
rename to langtools/test/tools/javac/diags/examples/ConflictingExports/exported/Class.java
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/langtools/test/tools/javac/diags/examples/ConflictingExports/module-info.java
similarity index 93%
rename from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
rename to langtools/test/tools/javac/diags/examples/ConflictingExports/module-info.java
index 4c3b290..7ce18dc 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ConflictingExports/module-info.java
@@ -21,9 +21,9 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+// key: compiler.err.conflicting.exports
 
-module DuplicateExports {
+module ConflictingExports {
      exports exported;
      exports exported;
 }
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java b/langtools/test/tools/javac/diags/examples/ConflictingExportsToModule/exported/Class.java
similarity index 100%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java
copy to langtools/test/tools/javac/diags/examples/ConflictingExportsToModule/exported/Class.java
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/langtools/test/tools/javac/diags/examples/ConflictingExportsToModule/module-info.java
similarity index 89%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to langtools/test/tools/javac/diags/examples/ConflictingExportsToModule/module-info.java
index 4c3b290..1c66f00 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ConflictingExportsToModule/module-info.java
@@ -21,9 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+// key: compiler.err.conflicting.exports.to.module
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+module ConflictingExports {
+     exports exported to java.base, java.base;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/ConflictingOpens/exported/Class.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/ConflictingOpens/exported/Class.java
index 9d2c8be..15d4133 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ConflictingOpens/exported/Class.java
@@ -21,7 +21,7 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+package opened;
+
+public class Class {
 }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/tools/javac/diags/examples/ConflictingOpens/module-info.java
similarity index 90%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to langtools/test/tools/javac/diags/examples/ConflictingOpens/module-info.java
index 242f168..40e39f9 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/tools/javac/diags/examples/ConflictingOpens/module-info.java
@@ -21,5 +21,9 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+// key: compiler.err.conflicting.opens
+
+module ConflictingOpens {
+     opens opened;
+     opens opened;
+}
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java b/langtools/test/tools/javac/diags/examples/ConflictingOpensToModule/module-info.java
similarity index 89%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
copy to langtools/test/tools/javac/diags/examples/ConflictingOpensToModule/module-info.java
index 4c3b290..0bf6508 100644
--- a/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ConflictingOpensToModule/module-info.java
@@ -21,9 +21,8 @@
  * questions.
  */
 
-// key: compiler.err.duplicate.exports
+// key: compiler.err.conflicting.opens.to.module
 
-module DuplicateExports {
-     exports exported;
-     exports exported;
+module ConflictingOpens {
+     opens opened to java.base, java.base;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/ConflictingOpensToModule/opened/Class.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/ConflictingOpensToModule/opened/Class.java
index 9d2c8be..15d4133 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ConflictingOpensToModule/opened/Class.java
@@ -21,7 +21,7 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+package opened;
+
+public class Class {
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/ExpectedModule.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/ExpectedModule.java
index 9d2c8be..2e350e2 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ExpectedModule.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+// key: compiler.err.expected.module
+
+open class ExpectedModule { }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/HasBeenDeprecatedModule.java
similarity index 92%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/HasBeenDeprecatedModule.java
index 9d2c8be..06fea802 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/HasBeenDeprecatedModule.java
@@ -21,7 +21,5 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+//key: compiler.warn.has.been.deprecated.module
+//options: -Xlint:deprecation
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/modulesourcepath/m1/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/modulesourcepath/m1/module-info.java
index 9d2c8be..f3b75a9 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/modulesourcepath/m1/module-info.java
@@ -21,7 +21,5 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+@Deprecated
+module m1 {}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/modulesourcepath/m2/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/modulesourcepath/m2/module-info.java
index 9d2c8be..7e4179d 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedModule/modulesourcepath/m2/module-info.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+module m2 {
+    requires m1;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/HasBeenDeprecatedRemovalModule.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/HasBeenDeprecatedRemovalModule.java
index 9d2c8be..cc32db0 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/HasBeenDeprecatedRemovalModule.java
@@ -21,7 +21,4 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+//key: compiler.warn.has.been.deprecated.for.removal.module
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/modulesourcepath/m1/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/modulesourcepath/m1/module-info.java
index 9d2c8be..1623fb5 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/modulesourcepath/m1/module-info.java
@@ -21,7 +21,5 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
-}
+@Deprecated(forRemoval=true)
+module m1 {}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/modulesourcepath/m2/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/modulesourcepath/m2/module-info.java
index 9d2c8be..7e4179d 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/HasBeenDeprecatedRemovalModule/modulesourcepath/m2/module-info.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+module m2 {
+    requires m1;
 }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/LeaksNotAccessibleNotRequiredTransitive.java
similarity index 93%
rename from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
rename to langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/LeaksNotAccessibleNotRequiredTransitive.java
index 242f168..52fdc58 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/LeaksNotAccessibleNotRequiredTransitive.java
@@ -21,5 +21,5 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
+// key: compiler.warn.leaks.not.accessible.not.required.transitive
 // options: -Xlint:exports
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m1/api1/Api1.java b/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m1/api1/Api1.java
similarity index 100%
rename from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m1/api1/Api1.java
rename to langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m1/api1/Api1.java
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m1/module-info.java b/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m1/module-info.java
similarity index 100%
rename from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m1/module-info.java
rename to langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m1/module-info.java
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m2/api2/Api2.java b/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m2/api2/Api2.java
similarity index 100%
rename from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m2/api2/Api2.java
rename to langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m2/api2/Api2.java
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m2/module-info.java b/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m2/module-info.java
similarity index 100%
rename from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/modulesourcepath/m2/module-info.java
rename to langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredTransitive/modulesourcepath/m2/module-info.java
diff --git a/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java b/langtools/test/tools/javac/diags/examples/NoOpensUnlessStrong/exported/Class.java
similarity index 100%
copy from langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java
copy to langtools/test/tools/javac/diags/examples/NoOpensUnlessStrong/exported/Class.java
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/NoOpensUnlessStrong/module-info.java
similarity index 91%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/NoOpensUnlessStrong/module-info.java
index 9d2c8be..480ecef 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/NoOpensUnlessStrong/module-info.java
@@ -21,7 +21,8 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+// key: compiler.err.no.opens.unless.strong
+
+open module ConflictingExports {
+     opens exported;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/NoPkgInModuleInfoJava/module-info.java
similarity index 93%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/NoPkgInModuleInfoJava/module-info.java
index 9d2c8be..1fbd517 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/NoPkgInModuleInfoJava/module-info.java
@@ -21,7 +21,9 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+//key: compiler.err.no.pkg.in.module-info.java
+
+package p;
+
+module m {
 }
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf.java
similarity index 90%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf.java
index 242f168..10a9dc7 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf.java
@@ -21,5 +21,4 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+// key: compiler.err.service.implementation.provider.return.must.be.subtype.of.service.interface
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/modulesourcepath/m/impl/Impl.java
similarity index 90%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/modulesourcepath/m/impl/Impl.java
index 242f168..8f417bf 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/modulesourcepath/m/impl/Impl.java
@@ -21,5 +21,10 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+package impl;
+
+public class Impl {
+    public static Impl provider() {
+        return null;
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/modulesourcepath/m/module-info.java
similarity index 94%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/modulesourcepath/m/module-info.java
index 9d2c8be..1b7506f 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplProviderReturnMustBeSubtypeOfServiceIntf/modulesourcepath/m/module-info.java
@@ -21,7 +21,6 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+module m {
+    provides java.lang.String with impl.Impl;
 }
diff --git a/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java b/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java
index 39d9049..6b93de4 100644
--- a/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java
+++ b/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java
@@ -83,10 +83,13 @@
         // need to ensure there is an empty java.base to avoid different error message
         Files.createDirectories(Paths.get("modules/java.base"));
         new JavacTask(tb)
-                .sources("module java.base { }")
+                .sources("module java.base { }",
+                         "package java.lang; public class Object {}")
                 .outdir("modules/java.base")
                 .run();
 
+        Files.delete(Paths.get("modules", "java.base", "java", "lang", "Object.class"));
+
         // ideally we'd have a better message for this case
         String[] mpOpts = { "--system", "none", "--module-path", "modules" };
         test(mpOpts, compilerErrorMessage);
diff --git a/langtools/test/tools/javac/generics/inference/8170410/T8170410.java b/langtools/test/tools/javac/generics/inference/8170410/T8170410.java
new file mode 100644
index 0000000..8dbeb5b
--- /dev/null
+++ b/langtools/test/tools/javac/generics/inference/8170410/T8170410.java
@@ -0,0 +1,23 @@
+/*
+ * @test
+ * @bug 8170410
+ * @summary inference: javac doesn't implement 18.2.5 correctly
+ * @compile T8170410.java
+ */
+
+class T8170410 {
+    interface CheckedSupplier<T extends Throwable, R> {
+        R get() throws T;
+    }
+
+    static <T extends Throwable, R> CheckedSupplier<T, R> checked(CheckedSupplier<T, R> checkedSupplier) {
+        return checkedSupplier;
+    }
+
+    static void test() {
+        checked(() -> null).get();
+        checked(T8170410::m).get();
+    }
+
+    static String m() { return ""; }
+}
diff --git a/langtools/test/tools/javac/modules/AnnotationProcessing.java b/langtools/test/tools/javac/modules/AnnotationProcessing.java
index 63b29ae..bcd8b4d 100644
--- a/langtools/test/tools/javac/modules/AnnotationProcessing.java
+++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java
@@ -245,7 +245,7 @@
             List<? extends ProvidesDirective> provides = ElementFilter.providesIn(modle.getDirectives());
             assertEquals(1, provides.size());
             assertEquals("api.Api", provides.iterator().next().getService().getQualifiedName().toString());
-            assertEquals("impl.Impl", provides.iterator().next().getImplementation().getQualifiedName().toString());
+            assertEquals("impl.Impl", provides.iterator().next().getImplementations().get(0).getQualifiedName().toString());
 
             return false;
         }
diff --git a/langtools/test/tools/javac/modules/AnnotationsOnModules.java b/langtools/test/tools/javac/modules/AnnotationsOnModules.java
new file mode 100644
index 0000000..454ad9e
--- /dev/null
+++ b/langtools/test/tools/javac/modules/AnnotationsOnModules.java
@@ -0,0 +1,405 @@
+/*
+ * 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 --add-modules and --limit-modules; also test the "enabled" modules.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.classfile
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavaTask ModuleTestBase
+ * @run main AnnotationsOnModules
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.TypeElement;
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
+import toolbox.JavacTask;
+import toolbox.Task.OutputKind;
+
+public class AnnotationsOnModules extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        AnnotationsOnModules t = new AnnotationsOnModules();
+        t.runTests();
+    }
+
+    @Test
+    public void testSimpleAnnotation(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "@Deprecated module m1 { }");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        new JavacTask(tb)
+                .options("--module-source-path", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll();
+
+        ClassFile cf = ClassFile.read(modulePath.resolve("m1").resolve("module-info.class"));
+        RuntimeVisibleAnnotations_attribute annotations = (RuntimeVisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeVisibleAnnotations);
+
+        if (annotations == null || annotations.annotations.length != 1) {
+            throw new AssertionError("Annotations not correct!");
+        }
+    }
+
+    @Test
+    public void testAnnotationWithImport(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "import m1.A; @A module m1 { }",
+                          "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface A {}");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        new JavacTask(tb)
+                .options("--module-source-path", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll();
+
+        ClassFile cf = ClassFile.read(modulePath.resolve("m1").resolve("module-info.class"));
+        RuntimeInvisibleAnnotations_attribute annotations = (RuntimeInvisibleAnnotations_attribute) cf.attributes.map.get(Attribute.RuntimeInvisibleAnnotations);
+
+        if (annotations == null || annotations.annotations.length != 1) {
+            throw new AssertionError("Annotations not correct!");
+        }
+    }
+
+    @Test
+    public void testModuleInfoAnnotationsInAPI(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "import m1.*; @A @Deprecated @E @E module m1 { }",
+                          "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface A {}",
+                          "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) @Repeatable(C.class) public @interface E {}",
+                          "package m1; import java.lang.annotation.*; @Target(ElementType.MODULE) public @interface C { public E[] value(); }");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        new JavacTask(tb)
+                .options("--module-source-path", moduleSrc.toString(),
+                         "-processor", AP.class.getName())
+                .outdir(modulePath)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll();
+
+        Path src = base.resolve("src");
+
+        tb.writeJavaFiles(src,
+                          "class T {}");
+
+        Path out = base.resolve("out");
+
+        Files.createDirectories(out);
+
+        new JavacTask(tb)
+                .options("--module-path", modulePath.toString(),
+                         "--add-modules", "m1",
+                         "-processor", AP.class.getName())
+                .outdir(out)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        new JavacTask(tb)
+                .options("--module-path", modulePath.toString() + File.pathSeparator + out.toString(),
+                         "--add-modules", "m1",
+                         "-processor", AP.class.getName(),
+                         "-proc:only")
+                .classes("m1/m1.A")
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class AP extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            ModuleElement m1 = processingEnv.getElementUtils().getModuleElement("m1");
+            Set<String> actualAnnotations = new HashSet<>();
+            Set<String> expectedAnnotations =
+                    new HashSet<>(Arrays.asList("@m1.A", "@java.lang.Deprecated", "@m1.C({@m1.E, @m1.E})"));
+
+            for (AnnotationMirror am : m1.getAnnotationMirrors()) {
+                actualAnnotations.add(am.toString());
+            }
+
+            if (!expectedAnnotations.equals(actualAnnotations)) {
+                throw new AssertionError("Incorrect annotations: " + actualAnnotations);
+            }
+
+            return false;
+        }
+
+    }
+
+    @Test
+    public void testModuleDeprecation(Path base) throws Exception {
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+
+        tb.writeJavaFiles(m1,
+                          "@Deprecated module m1 { }");
+
+        Path m2 = moduleSrc.resolve("m2");
+
+        tb.writeJavaFiles(m2,
+                          "@Deprecated module m2 { }");
+
+        Path m3 = moduleSrc.resolve("m3");
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        List<String> actual;
+        List<String> expected;
+
+        for (String suppress : new String[] {"", "@Deprecated ", "@SuppressWarnings(\"deprecation\") "}) {
+            tb.writeJavaFiles(m3,
+                              suppress + "module m3 {\n" +
+                              "    requires m1;\n" +
+                              "    exports api to m1, m2;\n" +
+                              "}",
+                              "package api; public class Api { }");
+            System.err.println("compile m3");
+            actual = new JavacTask(tb)
+                    .options("--module-source-path", moduleSrc.toString(),
+                             "-XDrawDiagnostics")
+                    .outdir(modulePath)
+                    .files(findJavaFiles(moduleSrc))
+                    .run()
+                    .writeAll()
+                    .getOutputLines(OutputKind.DIRECT);
+
+            if (suppress.isEmpty()) {
+                expected = Arrays.asList(
+                        "- compiler.note.deprecated.filename: module-info.java",
+                        "- compiler.note.deprecated.recompile");
+            } else {
+                expected = Arrays.asList("");
+            }
+
+            if (!expected.equals(actual)) {
+                throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress);
+            }
+
+            System.err.println("compile m3 with -Xlint:-deprecation");
+            actual = new JavacTask(tb)
+                    .options("--module-source-path", moduleSrc.toString(),
+                             "-XDrawDiagnostics",
+                             "-Xlint:deprecation")
+                    .outdir(modulePath)
+                    .files(findJavaFiles(moduleSrc))
+                    .run()
+                    .writeAll()
+                    .getOutputLines(OutputKind.DIRECT);
+
+            if (suppress.isEmpty()) {
+                expected = Arrays.asList(
+                        "module-info.java:2:14: compiler.warn.has.been.deprecated.module: m1",
+                        "1 warning");
+            } else {
+                expected = Arrays.asList("");
+            }
+
+            if (!expected.equals(actual)) {
+                throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress);
+            }
+
+            //load the deprecated module-infos from classfile:
+            System.err.println("compile m3 with -Xlint:-deprecation, loading deprecated modules from classes");
+            actual = new JavacTask(tb)
+                    .options("--module-path", modulePath.toString(),
+                             "-XDrawDiagnostics",
+                             "-Xlint:deprecation")
+                    .outdir(modulePath.resolve("m3"))
+                    .files(findJavaFiles(moduleSrc.resolve("m3")))
+                    .run()
+                    .writeAll()
+                    .getOutputLines(OutputKind.DIRECT);
+
+            if (!expected.equals(actual)) {
+                throw new AssertionError("Unexpected output: " + actual + "; suppress: " + suppress);
+            }
+        }
+    }
+
+    @Test
+    public void testAttributeValues(Path base) throws Exception {
+        class TestCase {
+            public final String extraDecl;
+            public final String decl;
+            public final String use;
+            public final String expectedAnnotations;
+
+            public TestCase(String extraDecl, String decl, String use, String expectedAnnotations) {
+                this.extraDecl = extraDecl;
+                this.decl = decl;
+                this.use = use;
+                this.expectedAnnotations = expectedAnnotations;
+            }
+        }
+
+        TestCase[] testCases = new TestCase[] {
+            new TestCase("package test; public enum E {A, B;}",
+                         "public E value();",
+                         "test.E.A",
+                         "@test.A(test.E.A)"),
+            new TestCase("package test; public enum E {A, B;}",
+                         "public E[] value();",
+                         "{test.E.A, test.E.B}",
+                         "@test.A({test.E.A, test.E.B})"),
+            new TestCase("package test; public class Extra {}",
+                         "public Class value();",
+                         "test.Extra.class",
+                         "@test.A(test.Extra.class)"),
+            new TestCase("package test; public class Extra {}",
+                         "public Class[] value();",
+                         "{test.Extra.class, String.class}",
+                         "@test.A({test.Extra.class, java.lang.String.class})"),
+            new TestCase("package test; public @interface Extra { public Class value(); }",
+                         "public test.Extra value();",
+                         "@test.Extra(String.class)",
+                         "@test.A(@test.Extra(java.lang.String.class))"),
+            new TestCase("package test; public @interface Extra { public Class value(); }",
+                         "public test.Extra[] value();",
+                         "{@test.Extra(String.class), @test.Extra(Integer.class)}",
+                         "@test.A({@test.Extra(java.lang.String.class), @test.Extra(java.lang.Integer.class)})"),
+            new TestCase("package test; public class Any { }",
+                         "public int value();",
+                         "1",
+                         "@test.A(1)"),
+            new TestCase("package test; public class Any { }",
+                         "public int[] value();",
+                         "{1, 2}",
+                         "@test.A({1, 2})"),
+        };
+
+        Path extraSrc = base.resolve("extra-src");
+        tb.writeJavaFiles(extraSrc,
+                          "class Any {}");
+
+        int count = 0;
+
+        for (TestCase tc : testCases) {
+            Path testBase = base.resolve(String.valueOf(count));
+            Path moduleSrc = testBase.resolve("module-src");
+            Path m = moduleSrc.resolve("m");
+
+            tb.writeJavaFiles(m,
+                              "@test.A(" + tc.use + ") module m { }",
+                              "package test; @java.lang.annotation.Target(java.lang.annotation.ElementType.MODULE) public @interface A { " + tc.decl + "}",
+                              tc.extraDecl);
+
+            Path modulePath = testBase.resolve("module-path");
+
+            Files.createDirectories(modulePath);
+
+            new JavacTask(tb)
+                .options("--module-source-path", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+
+            Path classes = testBase.resolve("classes");
+
+            Files.createDirectories(classes);
+
+            new JavacTask(tb)
+                .options("--module-path", modulePath.toString(),
+                         "--add-modules", "m",
+                         "-processorpath", System.getProperty("test.classes"),
+                         "-processor", ProxyTypeValidator.class.getName(),
+                         "-A" + OPT_EXPECTED_ANNOTATIONS + "=" + tc.expectedAnnotations)
+                .outdir(classes)
+                .files(findJavaFiles(extraSrc))
+                .run()
+                .writeAll();
+        }
+    }
+
+    private static final String OPT_EXPECTED_ANNOTATIONS = "expectedAnnotations";
+
+    @SupportedAnnotationTypes("*")
+    @SupportedOptions(OPT_EXPECTED_ANNOTATIONS)
+    public static final class ProxyTypeValidator extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            ModuleElement m = processingEnv.getElementUtils().getModuleElement("m");
+            String actualTypes = m.getAnnotationMirrors()
+                                  .stream()
+                                  .map(am -> am.toString())
+                                  .collect(Collectors.joining(", "));
+            if (!Objects.equals(actualTypes, processingEnv.getOptions().get(OPT_EXPECTED_ANNOTATIONS))) {
+                throw new IllegalStateException("Expected annotations not found, actual: " + actualTypes);
+            }
+            return false;
+        }
+
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/AutomaticModules.java b/langtools/test/tools/javac/modules/AutomaticModules.java
index 5cb2ea3..53beb76 100644
--- a/langtools/test/tools/javac/modules/AutomaticModules.java
+++ b/langtools/test/tools/javac/modules/AutomaticModules.java
@@ -193,7 +193,7 @@
         Files.createDirectories(depClasses);
 
         tb.writeJavaFiles(depSrc,
-                          "module m1 { requires public automatic; }",
+                          "module m1 { requires transitive automatic; }",
                           "package dep; public class Dep { api.Api api; }");
 
         new JavacTask(tb)
@@ -261,7 +261,7 @@
         Path moduleSrc = base.resolve("module-src");
 
         tb.writeJavaFiles(moduleSrc.resolve("m1"),
-                          "module m1 { requires automaticA; }",
+                          "module m1 { requires static automaticA; }",
                           "package impl; public class Impl { apiA.Api a; apiB.Api b; m2.M2 m;}");
 
         tb.writeJavaFiles(moduleSrc.resolve("m2"),
@@ -308,4 +308,54 @@
             throw new Exception("expected output not found: " + log);
         }
     }
+
+    @Test
+    public void testDropTrailingVersion(Path base) throws Exception {
+        Path legacySrc = base.resolve("legacy-src");
+        tb.writeJavaFiles(legacySrc,
+                          "package api; public class Api {}");
+        Path legacyClasses = base.resolve("legacy-classes");
+        Files.createDirectories(legacyClasses);
+
+        String log = new JavacTask(tb)
+                .options()
+                .outdir(legacyClasses)
+                .files(findJavaFiles(legacySrc))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty()) {
+            throw new Exception("unexpected output: " + log);
+        }
+
+        Path modulePath = base.resolve("module-path");
+
+        Files.createDirectories(modulePath);
+
+        Path jar = modulePath.resolve("test1.jar");
+
+        new JarTask(tb, jar)
+          .baseDir(legacyClasses)
+          .files("api/Api.class")
+          .run();
+
+        Path moduleSrc = base.resolve("module-src");
+        Path m = moduleSrc.resolve("m");
+
+        Path classes = base.resolve("classes");
+
+        Files.createDirectories(classes);
+
+        tb.writeJavaFiles(m,
+                          "module m { requires test; }",
+                          "package impl; public class Impl { public void e(api.Api api) { } }");
+
+        new JavacTask(tb)
+                .options("--module-source-path", moduleSrc.toString(), "--module-path", modulePath.toString())
+                .outdir(classes)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+    }
 }
diff --git a/langtools/test/tools/javac/modules/EdgeCases.java b/langtools/test/tools/javac/modules/EdgeCases.java
index 1997a3d..8624298 100644
--- a/langtools/test/tools/javac/modules/EdgeCases.java
+++ b/langtools/test/tools/javac/modules/EdgeCases.java
@@ -206,7 +206,7 @@
 
         Files.createDirectories(modulePath);
 
-        Path automaticJar = modulePath.resolve("m1-1.0.jar");
+        Path automaticJar = modulePath.resolve("a-1.0.jar");
 
         new JarTask(tb, automaticJar)
           .baseDir(automaticClasses)
@@ -216,11 +216,11 @@
         Path src = base.resolve("src");
         Path src_m2 = src.resolve("m2");
         tb.writeJavaFiles(src_m2,
-                          "module m2 { requires m1; exports api2; }",
+                          "module m2 { requires a; exports api2; }",
                           "package api2; public class Api2 { public static api1.Api1 get() { return null; } }");
         Path src_m3 = src.resolve("m3");
         tb.writeJavaFiles(src_m3,
-                          "module m3 { requires m1; requires m2; }",
+                          "module m3 { requires a; requires m2; }",
                           "package test; public class Test { { api2.Api2.get(); api1.Api1 a1; } }");
         Path classes = base.resolve("classes");
         tb.createDirectories(classes);
@@ -459,4 +459,29 @@
 
         syms.java_base.getDirectives();
     }
+
+    @Test
+    public void testPackageInModuleInfo(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Files.createDirectories(src);
+        tb.writeJavaFiles(src, "package p; module foo { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = new JavacTask(tb)
+            .options("-XDrawDiagnostics", "-XDshould-stop.ifError=FLOW")
+            .outdir(classes)
+            .files(findJavaFiles(src))
+            .run(Expect.FAIL)
+            .writeAll()
+            .getOutputLines(OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+                "module-info.java:1:1: compiler.err.no.pkg.in.module-info.java",
+                "1 error");
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
 }
diff --git a/langtools/test/tools/javac/modules/ExportsUnexported.java b/langtools/test/tools/javac/modules/ExportsUnexported.java
index 93cd311..691eaea 100644
--- a/langtools/test/tools/javac/modules/ExportsUnexported.java
+++ b/langtools/test/tools/javac/modules/ExportsUnexported.java
@@ -169,7 +169,7 @@
                           "    exports api;\n" +
                           "    exports qapi1 to qual1;\n" +
                           "    exports qapi2 to qual1, qual2;\n" +
-                          "    requires public lib1;\n" +
+                          "    requires transitive lib1;\n" +
                           "    requires lib2;\n" +
                           "}\n",
                           "package api;\n" +
@@ -209,7 +209,7 @@
                 .getOutputLines(Task.OutputKind.DIRECT);
 
         List<String> expected = Arrays.asList(
-            "Api.java:4:16: compiler.warn.leaks.not.accessible.not.required.public: kindname.class, lib2.Lib2, lib2",
+            "Api.java:4:16: compiler.warn.leaks.not.accessible.not.required.transitive: kindname.class, lib2.Lib2, lib2",
             "Api.java:5:17: compiler.warn.leaks.not.accessible.unexported.qualified: kindname.class, qapi1.QApi1, api",
             "Api.java:6:16: compiler.warn.leaks.not.accessible.unexported: kindname.class, impl.Impl, api",
             "- compiler.err.warnings.and.werror",
diff --git a/langtools/test/tools/javac/modules/GetLocationForModuleTest.java b/langtools/test/tools/javac/modules/GetLocationForModuleTest.java
new file mode 100644
index 0000000..b840f54
--- /dev/null
+++ b/langtools/test/tools/javac/modules/GetLocationForModuleTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8162712
+ * @summary StandardJavaFileManager.getModuleLocation() can't find a module
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.JavacTask toolbox.ToolBox
+ * @run main GetLocationForModuleTest
+ */
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.util.*;
+import javax.tools.*;
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+public class GetLocationForModuleTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new GetLocationForModuleTest().run(Paths.get("."));
+    }
+
+    public void run(Path base) throws Exception {
+        // Set up some trivial modules
+        Path moduleSrc = base.resolve("module-src");
+        Path m1 = moduleSrc.resolve("m1");
+        tb.writeJavaFiles(m1, "module m1 { }");
+        Path m2 = moduleSrc.resolve("m2");
+        tb.writeJavaFiles(m2, "module m2 { }");
+
+        Path modulePath = base.resolve("module-path");
+        Files.createDirectories(modulePath);
+        new JavacTask(tb)
+                .options("--module-source-path", moduleSrc.toString())
+                .outdir(modulePath)
+                .files(findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+
+        // Init file manager
+        StandardJavaFileManager fm =
+                ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null);
+        fm.setLocationFromPaths(StandardLocation.MODULE_PATH, Arrays.asList(modulePath));
+
+        // Test
+        test(fm, StandardLocation.SYSTEM_MODULES, "java.base", "java.compiler");
+        test(fm, StandardLocation.MODULE_PATH, "m1", "m2");
+    }
+
+    void test(JavaFileManager fm, JavaFileManager.Location locn, String... mods) throws IOException {
+        for (String mod : mods) {
+            JavaFileManager.Location modLocn = fm.getLocationForModule(locn, mod);
+            if (modLocn == null) {
+                error(locn.getName() + ": can't find " + mod);
+            } else {
+                System.err.println(locn.getName() + ": found " + mod + ": " + modLocn.getName());
+            }
+        }
+    }
+}
+
diff --git a/langtools/test/tools/javac/modules/GraphsTest.java b/langtools/test/tools/javac/modules/GraphsTest.java
index 26118ff..e26a859 100644
--- a/langtools/test/tools/javac/modules/GraphsTest.java
+++ b/langtools/test/tools/javac/modules/GraphsTest.java
@@ -55,19 +55,19 @@
 
     /**
      * Tests diamond graph with an automatic module added in.
-     * +-------------+          +--------------------+         +------------------+
-     * | module M    |          | module N           |         | module O         |
-     * |             | ----->   |                    | --->    |                  |  --> J.jar
-     * | require N   |          | requires public  O |         |                  |
-     * | require L   |          |                    |         +------------------+
-     * +-------------+          +--------------------+                  ^
+     * +-------------+          +-----------------------+         +------------------+
+     * | module M    |          | module N              |         | module O         |
+     * |             | ----->   |                       | --->    |                  |  --> J.jar
+     * | require N   |          | requires transitive O |         |                  |
+     * | require L   |          |                       |         +------------------+
+     * +-------------+          +-----------------------+                  ^
      *       |                                                          |
-     *       |                  +--------------------+                  |
-     *       ------------------>| module L           |                  |
-     *                          |                    |------------------
-     *                          | requires public O  |
-     *                          |                    |
-     *                          +--------------------+
+     *       |                  +-----------------------+                  |
+     *       ------------------>| module L              |                  |
+     *                          |                       |------------------
+     *                          | requires transitive O |
+     *                          |                       |
+     *                          +-----------------------+
      *
      */
     @Test
@@ -92,18 +92,18 @@
 
         new ModuleBuilder(tb, "O")
                 .exports("openO")
-                .requiresPublic("J", jarModules)
+                .requiresTransitive("J", jarModules)
                 .classes("package openO; public class O { openJ.J j; }")
                 .classes("package closedO; public class O { }")
                 .build(modSrc, modules);
         new ModuleBuilder(tb, "N")
-                .requiresPublic("O", modules, jarModules)
+                .requiresTransitive("O", modules, jarModules)
                 .exports("openN")
                 .classes("package openN; public class N { }")
                 .classes("package closedN; public class N { }")
                 .build(modSrc, modules);
         new ModuleBuilder(tb, "L")
-                .requiresPublic("O", modules, jarModules)
+                .requiresTransitive("O", modules, jarModules)
                 .exports("openL")
                 .classes("package openL; public class L { }")
                 .classes("package closedL; public class L { }")
@@ -171,18 +171,18 @@
     /**
      * Tests graph where module M reexport package of N, but N export the package only to M.
      *
-    +-------------+        +--------------------+        +---------------+
-    | module L    |        | module M           |        | module N      |
-    |             | -----> |                    | -----> |               |
-    |  requires M |        |  requires public N |        | exports P to M|
-    +-------------+        |                    |        +---------------+
-                           +--------------------+
+    +-------------+        +------------------------+        +---------------+
+    | module L    |        | module M               |        | module N      |
+    |             | -----> |                        | -----> |               |
+    |  requires M |        |  requires transitive N |        | exports P to M|
+    +-------------+        |                        |        +---------------+
+                           +------------------------+
     */
     @Test
     public void reexportOfQualifiedExport(Path base) throws Exception {
         Path modSrc = base.resolve("modSrc");
         new ModuleBuilder(tb, "M")
-                .requiresPublic("N")
+                .requiresTransitive("N")
                 .write(modSrc);
         new ModuleBuilder(tb, "N")
                 .exportsTo("pack", "M")
diff --git a/langtools/test/tools/javac/modules/InvalidModuleDirective/module-info.java b/langtools/test/tools/javac/modules/InvalidModuleDirective/module-info.java
index fc20ece..652b2d1 100644
--- a/langtools/test/tools/javac/modules/InvalidModuleDirective/module-info.java
+++ b/langtools/test/tools/javac/modules/InvalidModuleDirective/module-info.java
@@ -8,8 +8,8 @@
 module java.transaction {
   requires java.base;
   resuires javax.interceptor.javax.interceptor.api;
-  requires public javax.enterprise.cdi.api;
-  requires public java.sql;
-  requires public java.rmi;
+  requires transitive javax.enterprise.cdi.api;
+  requires transitive java.sql;
+  requires transitive java.rmi;
   export javax.transaction;
 }
diff --git a/langtools/test/tools/javac/modules/ModuleInfoTest.java b/langtools/test/tools/javac/modules/ModuleInfoTest.java
index 62200b0..7adec9b 100644
--- a/langtools/test/tools/javac/modules/ModuleInfoTest.java
+++ b/langtools/test/tools/javac/modules/ModuleInfoTest.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8158123
+ * @bug 8158123 8161906 8162713
  * @summary tests for module declarations
  * @library /tools/lib
  * @modules
@@ -34,6 +34,7 @@
  * @run main ModuleInfoTest
  */
 
+import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
@@ -203,12 +204,12 @@
      * Verify that a multi-module loop is detected.
      */
     @Test
-    public void testRequiresPublicLoop(Path base) throws Exception {
+    public void testRequiresTransitiveLoop(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
         Path src_m2 = src.resolve("m2");
-        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires public m3; }");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires transitive m3; }");
         Path src_m3 = src.resolve("m3");
         tb.writeFile(src_m3.resolve("module-info.java"), "module m3 { requires m1; }");
 
@@ -223,7 +224,7 @@
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
 
-        if (!log.contains("module-info.java:1:29: compiler.err.cyclic.requires: m3"))
+        if (!log.contains("module-info.java:1:33: compiler.err.cyclic.requires: m3"))
             throw new Exception("expected output not found");
     }
 
@@ -254,36 +255,15 @@
     }
 
     /**
-     * Verify that duplicate exported packages are detected.
+     * Verify that duplicate requires are detected.
      */
     @Test
-    public void testDuplicateExports_packages(Path base) throws Exception {
+    public void testDuplicateRequiresTransitiveStatic(Path base) throws Exception {
         Path src = base.resolve("src");
-        tb.writeJavaFiles(src, "module m1 { exports p; exports p; }");
-
-        Path classes = base.resolve("classes");
-        Files.createDirectories(classes);
-
-        String log = new JavacTask(tb)
-                .options("-XDrawDiagnostics")
-                .outdir(classes)
-                .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutput(Task.OutputKind.DIRECT);
-
-        if (!log.contains("module-info.java:1:32: compiler.err.duplicate.exports: p"))
-            throw new Exception("expected output not found");
-    }
-
-    /**
-     * Verify that duplicate exported packages are detected.
-     */
-    @Test
-    public void testDuplicateExports_packages2(Path base) throws Exception {
-        Path src = base.resolve("src");
-        tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports p to m2; }");
-        tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
+        Path src_m1 = src.resolve("m1");
+        tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeFile(src_m2.resolve("module-info.java"), "module m2 { requires transitive m1; requires static m1; }");
 
         Path classes = base.resolve("classes");
         Files.createDirectories(classes);
@@ -296,15 +276,115 @@
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
 
-        if (!log.contains("module-info.java:1:32: compiler.err.duplicate.exports: p"))
+        if (!log.contains("module-info.java:1:53: compiler.err.duplicate.requires: m1"))
             throw new Exception("expected output not found");
     }
 
     /**
+     * Verify that duplicate exported packages are detected correctly.
+     */
+    @Test
+    public void testConflictingExports_packages(Path base) throws Exception {
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports q;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports p;",
+                                          "module-info.java:1:32: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p; opens p;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports p; exports p to m2;",
+                                          "module-info.java:1:32: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p; opens p to m2;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p; exports p;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p; opens p;",
+                                          "module-info.java:1:28: compiler.err.conflicting.opens: p");
+        verifyConflictingExports_packages(base,
+                                          "opens p; exports p to m2;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p; opens p to m2;",
+                                          "module-info.java:1:28: compiler.err.conflicting.opens: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports p;",
+                                          "module-info.java:1:38: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; opens p;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports p to m2;",
+                                          "module-info.java:1:43: compiler.err.conflicting.exports.to.module: m2");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; opens p to m2;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p to m2; exports p;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p to m2; opens p;",
+                                          "module-info.java:1:34: compiler.err.conflicting.opens: p");
+        verifyConflictingExports_packages(base,
+                                          "opens p to m2; exports p to m2;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p to m2; opens p to m2;",
+                                          "module-info.java:1:34: compiler.err.conflicting.opens: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; exports p to m3;",
+                                          "module-info.java:1:38: compiler.err.conflicting.exports: p");
+        verifyConflictingExports_packages(base,
+                                          "exports p to m2; opens p to m3;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p to m2; exports p to m3;",
+                                          null);
+        verifyConflictingExports_packages(base,
+                                          "opens p to m2; opens p to m3;",
+                                          "module-info.java:1:34: compiler.err.conflicting.opens: p");
+    }
+
+    private void verifyConflictingExports_packages(Path base, String code, String expected) throws Exception {
+        Files.createDirectories(base);
+        tb.cleanDirectory(base);
+
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1"),
+                          "module m1 { " + code + " }",
+                          "package p; public class P {}",
+                          "package q; public class Q {}");
+        tb.writeJavaFiles(src.resolve("m2"),
+                          "module m2 { requires m1; }");
+        tb.writeJavaFiles(src.resolve("m3"),
+                          "module m3 { requires m1; }");
+
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--module-source-path", src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(expected != null ? Task.Expect.FAIL : Task.Expect.SUCCESS)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (expected != null && !log.contains(expected))
+            throw new Exception("expected output not found, actual output: " + log);
+    }
+
+    /**
      * Verify that duplicate exported packages are detected.
      */
     @Test
-    public void testDuplicateExports_modules(Path base) throws Exception {
+    public void testConflictingExports_modules(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
@@ -322,7 +402,7 @@
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
 
-        if (!log.contains("module-info.java:1:30: compiler.err.duplicate.exports: m1"))
+        if (!log.contains("module-info.java:1:30: compiler.err.conflicting.exports.to.module: m1"))
             throw new Exception("expected output not found");
     }
 
@@ -363,8 +443,12 @@
                     .writeAll()
                     .getOutput(Task.OutputKind.DIRECT);
 
-            if (!log.matches("(?s)^module\\-info\\.java:\\d+:\\d+: compiler\\.err\\.expected: token\\.identifier.*"))
-                throw new Exception("expected output not found");
+            String expect_prefix = "(?s)^module\\-info\\.java:\\d+:\\d+: ";
+            String expect_message = "compiler\\.err\\.expected: token\\.identifier";
+            String expect_suffix = ".*";
+            String expect = expect_prefix + expect_message + expect_suffix;
+            if (!log.matches(expect))
+                throw new Exception("expected output not found for: " + moduleInfo + "; actual: " + log);
         }
     }
 }
diff --git a/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java b/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java
index 7e0917c..3cd1e78 100644
--- a/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java
+++ b/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java
@@ -85,4 +85,29 @@
             assertNotNull("docCommentTree", docCommentTree);
         }
     }
+
+    @Test
+    public void testTreePathForModuleDeclWithImport(Path base) throws Exception {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+            Path src = base.resolve("src");
+            tb.writeJavaFiles(src, "import java.lang.Deprecated; /** Test module */ @Deprecated module m1 {}");
+
+            Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(src));
+            JavacTask task = (JavacTask) compiler.getTask(null, fm, null, null, null, files);
+
+            task.analyze();
+            JavacTrees trees = JavacTrees.instance(task);
+            ModuleElement mdle = (ModuleElement) task.getElements().getModuleElement("m1");
+
+            TreePath path = trees.getPath(mdle);
+            assertNotNull("path", path);
+
+            ModuleElement mdle1 = (ModuleElement) trees.getElement(path);
+            assertNotNull("mdle1", mdle1);
+
+            DocCommentTree docCommentTree = trees.getDocCommentTree(mdle);
+            assertNotNull("docCommentTree", docCommentTree);
+        }
+    }
 }
diff --git a/langtools/test/tools/javac/modules/ModulePathTest.java b/langtools/test/tools/javac/modules/ModulePathTest.java
index ba7c48d..e5efb2b 100644
--- a/langtools/test/tools/javac/modules/ModulePathTest.java
+++ b/langtools/test/tools/javac/modules/ModulePathTest.java
@@ -178,7 +178,7 @@
                 .run()
                 .writeAll();
 
-        Path moduleJar = base.resolve("m1.jar");
+        Path moduleJar = base.resolve("a.jar");
         new JarTask(tb, moduleJar)
           .baseDir(jarClasses)
           .files("p/CC.class")
@@ -191,7 +191,7 @@
 
         new JavacTask(tb, Task.Mode.CMDLINE)
                 .outdir(classes)
-                .options("--module-path", moduleJar.toString(), "--add-modules", "m1")
+                .options("--module-path", moduleJar.toString(), "--add-modules", "a")
                 .files(findJavaFiles(src))
                 .run()
                 .writeAll();
diff --git a/langtools/test/tools/javac/modules/OpenModulesTest.java b/langtools/test/tools/javac/modules/OpenModulesTest.java
new file mode 100644
index 0000000..9d477fb
--- /dev/null
+++ b/langtools/test/tools/javac/modules/OpenModulesTest.java
@@ -0,0 +1,287 @@
+/*
+ * 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 tests for multi-module mode compilation
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
+ * @run main OpenModulesTest
+ */
+
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.Attributes;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ClassWriter;
+import com.sun.tools.classfile.Module_attribute;
+import toolbox.JavacTask;
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.Task.OutputKind;
+
+public class OpenModulesTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new OpenModulesTest().runTests();
+    }
+
+    @Test
+    public void testStrongModule(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "module m1 { exports api1; opens api2; }",
+                          "package api1; public class Api1 {}",
+                          "package api2; public class Api2 {}",
+                          "package impl; public class Impl {}");
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        tb.createDirectories(m1Classes);
+
+        String log = new JavacTask(tb)
+                .outdir(m1Classes)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+
+        String decompiled = new JavapTask(tb)
+                .options("--system", "none", "-bootclasspath", "")
+                .classes(m1Classes.resolve("module-info.class").toString())
+                .run()
+                .writeAll()
+                .getOutput(OutputKind.DIRECT)
+                .replace(System.getProperty("line.separator"), "\n");
+
+        String expected = "module m1 {\n" +
+                          "  requires java.base;\n" +
+                          "  exports api1;\n" +
+                          "  opens api2;\n" +
+                          "}";
+
+        if (!decompiled.contains(expected)) {
+            throw new Exception("expected output not found: " + decompiled);
+        }
+
+        //compiling against a strong module read from binary:
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m2,
+                          "module m2 { requires m1; }",
+                          "package test; public class Test { api1.Api1 a1; api2.Api2 a2; }");
+        Path m2Classes = classes.resolve("m2");
+        tb.createDirectories(m2Classes);
+
+        List<String> log2 = new JavacTask(tb)
+                .options("--module-path", m1Classes.toString(),
+                         "-XDrawDiagnostics")
+                .outdir(m2Classes)
+                .files(findJavaFiles(m2))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected2 = Arrays.asList("Test.java:1:53: compiler.err.doesnt.exist: api2",
+                                               "1 error");
+        if (!Objects.equals(log2, expected2))
+            throw new Exception("expected output not found: " + log2);
+    }
+
+    @Test
+    public void testOpenModule(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "open module m1 { exports api1; }",
+                          "package api1; public class Api1 {}",
+                          "package api2; public class Api2 {}",
+                          "package impl; public class Impl {}");
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        tb.createDirectories(m1Classes);
+
+        String log = new JavacTask(tb)
+                .outdir(m1Classes)
+                .files(findJavaFiles(m1))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.isEmpty())
+            throw new Exception("expected output not found: " + log);
+
+        String decompiled = new JavapTask(tb)
+                .options("--system", "none", "-bootclasspath", "")
+                .classes(m1Classes.resolve("module-info.class").toString())
+                .run()
+                .writeAll()
+                .getOutput(OutputKind.DIRECT)
+                .replace(System.getProperty("line.separator"), "\n");
+
+        String expected = "open module m1 {\n" +
+                          "  requires java.base;\n" +
+                          "  exports api1;\n" +
+                          "}";
+
+        if (!decompiled.contains(expected)) {
+            throw new Exception("expected output not found: " + decompiled);
+        }
+
+        //compiling against a ordinary module read from binary:
+        Path m2 = base.resolve("m2");
+        tb.writeJavaFiles(m2,
+                          "module m2 { requires m1; }",
+                          "package test; public class Test { api1.Api1 a1; api2.Api2 a2; }");
+        Path m2Classes = classes.resolve("m2");
+        tb.createDirectories(m2Classes);
+
+        List<String> log2 = new JavacTask(tb)
+                .options("--module-path", m1Classes.toString(),
+                         "-XDrawDiagnostics")
+                .outdir(m2Classes)
+                .files(findJavaFiles(m2))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected2 = Arrays.asList("Test.java:1:53: compiler.err.doesnt.exist: api2",
+                                               "1 error");
+        if (!Objects.equals(log2, expected2))
+            throw new Exception("expected output not found: " + log2);
+    }
+
+    @Test
+    public void testOpenModuleNoOpens(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "open module m1 { exports api1; opens api2; }",
+                          "package api1; public class Api1 {}",
+                          "package api2; public class Api2 {}",
+                          "package impl; public class Impl {}");
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        tb.createDirectories(m1Classes);
+
+        List<String> log = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(m1Classes)
+                .files(findJavaFiles(m1))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("module-info.java:1:32: compiler.err.no.opens.unless.strong",
+                                              "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+
+    }
+
+    @Test
+    public void testNonZeroOpensInOpen(Path base) throws Exception {
+        Path m1 = base.resolve("m1");
+        tb.writeJavaFiles(m1,
+                          "module m1 { opens api; }",
+                          "package api; public class Api {}");
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        tb.createDirectories(m1Classes);
+
+        new JavacTask(tb)
+            .options("-XDrawDiagnostics")
+            .outdir(m1Classes)
+            .files(findJavaFiles(m1))
+            .run(Expect.SUCCESS)
+            .writeAll();
+
+        Path miClass = m1Classes.resolve("module-info.class");
+        ClassFile cf = ClassFile.read(miClass);
+        Module_attribute module = (Module_attribute) cf.attributes.map.get(Attribute.Module);
+        Module_attribute newModule = new Module_attribute(module.attribute_name_index,
+                                                          module.module_name,
+                                                          module.module_flags | Module_attribute.ACC_OPEN,
+                                                          module.requires,
+                                                          module.exports,
+                                                          module.opens,
+                                                          module.uses_index,
+                                                          module.provides);
+        Map<String, Attribute> attrs = new HashMap<>(cf.attributes.map);
+
+        attrs.put(Attribute.Module, newModule);
+
+        Attributes newAttributes = new Attributes(attrs);
+        ClassFile newClassFile = new ClassFile(cf.magic,
+                                               cf.minor_version,
+                                               cf.major_version,
+                                               cf.constant_pool,
+                                               cf.access_flags,
+                                               cf.this_class,
+                                               cf.super_class,
+                                               cf.interfaces,
+                                               cf.fields,
+                                               cf.methods,
+                                               newAttributes);
+
+        try (OutputStream out = Files.newOutputStream(miClass)) {
+            new ClassWriter().write(newClassFile, out);
+        }
+
+        Path test = base.resolve("test");
+        tb.writeJavaFiles(test,
+                          "package impl; public class Impl extends api.Api {}");
+        Path testClasses = base.resolve("test-classes");
+        tb.createDirectories(testClasses);
+
+        List<String> log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--module-path", classes.toString(),
+                         "--add-modules", "m1")
+                .outdir(testClasses)
+                .files(findJavaFiles(test))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList("- compiler.err.cant.access: m1.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.non.zero.opens: m1))",
+                                              "1 error");
+
+        if (!expected.equals(log))
+            throw new Exception("expected output not found: " + log);
+    }
+
+}
diff --git a/langtools/test/tools/javac/modules/PatchModulesTest.java b/langtools/test/tools/javac/modules/PatchModulesTest.java
index 648ba49..dde0c53 100644
--- a/langtools/test/tools/javac/modules/PatchModulesTest.java
+++ b/langtools/test/tools/javac/modules/PatchModulesTest.java
@@ -28,7 +28,7 @@
  * @library /tools/lib
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
- *      jdk.compiler/com.sun.tools.javac.file
+ *      jdk.compiler/com.sun.tools.javac.file:+open
  *      jdk.compiler/com.sun.tools.javac.main
  * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main PatchModulesTest
diff --git a/langtools/test/tools/javac/modules/ProvidesTest.java b/langtools/test/tools/javac/modules/ProvidesTest.java
index cef2f52..b3aaa06 100644
--- a/langtools/test/tools/javac/modules/ProvidesTest.java
+++ b/langtools/test/tools/javac/modules/ProvidesTest.java
@@ -41,7 +41,6 @@
 import toolbox.JavacTask;
 import toolbox.Task;
 import toolbox.Task.Expect;
-import toolbox.ToolBox;
 
 public class ProvidesTest extends ModuleTestBase {
     public static void main(String... args) throws Exception {
@@ -426,4 +425,96 @@
                 .run(Expect.SUCCESS)
                 .writeAll();
     }
+
+    @Test
+    public void testFactory(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { exports p1; provides p1.C1 with p2.C2; }",
+                "package p1; public interface C1 { }",
+                "package p2; public class C2 { public static p1.C1 provider() { return null; } }");
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        List<String> output;
+        List<String> expected;
+
+        tb.writeJavaFiles(src,
+                "package p2; public class C2 { public p1.C1 provider() { return null; } }");
+
+        output = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.must.be.subtype.of.service.interface",
+                                 "1 error");
+
+        if (!expected.equals(output)) {
+            throw new Exception("Expected output not found. Output: " + output);
+        }
+
+        tb.writeJavaFiles(src,
+                "package p2; public class C2 { static p1.C1 provider() { return null; } }");
+
+        output = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.must.be.subtype.of.service.interface",
+                                 "1 error");
+
+        if (!expected.equals(output)) {
+            throw new Exception("Expected output not found. Output: " + output);
+        }
+
+        tb.writeJavaFiles(src,
+                "package p2; public class C2 { public static Object provider() { return null; } }");
+
+        output = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.provider.return.must.be.subtype.of.service.interface",
+                                 "1 error");
+
+        if (!expected.equals(output)) {
+            throw new Exception("Expected output not found. Output: " + output);
+        }
+
+        tb.writeJavaFiles(src,
+                "package p2; public class C2 { public static p1.C1 provider = new p1.C1() {}; }");
+
+        output = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(Files.createDirectories(base.resolve("classes")))
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList("module-info.java:1:46: compiler.err.service.implementation.must.be.subtype.of.service.interface",
+                                 "1 error");
+
+        if (!expected.equals(output)) {
+            throw new Exception("Expected output not found. Output: " + output);
+        }
+    }
 }
diff --git a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java
index da1f5c8..b365edb 100644
--- a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java
+++ b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java
@@ -82,7 +82,7 @@
                 .run(Task.Expect.FAIL)
                 .writeAll()
                 .getOutput(Task.OutputKind.DIRECT);
-        if (!log.contains("module-info.java:1:39: compiler.err.duplicate.provides"))
+        if (!log.contains("module-info.java:1:61: compiler.err.duplicate.provides"))
             throw new Exception("expected output not found");
     }
 }
diff --git a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java
index b36944b..8d76c9e 100644
--- a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java
+++ b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java
@@ -22,7 +22,7 @@
  */
 
 /**
- * @test 8144342 8149658
+ * @test 8144342 8149658 8162713
  * @summary javac doesn't report errors if module exports non-existent package
  * @library /tools/lib
  * @modules
@@ -103,4 +103,45 @@
         if (!log.contains("module-info.java:1:20: compiler.err.package.empty.or.not.found: p1"))
             throw new Exception("expected output not found");
     }
+
+    @Test
+    public void testExportPrivateEmptyPackage(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { opens p; }");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+        if (!log.contains("module-info.java:1:18: compiler.err.package.empty.or.not.found: p"))
+            throw new Exception("expected output not found, actual output: " + log);
+    }
+
+    @Test
+    public void testExportPrivateOnlyWithResources(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { opens p; }");
+        Path resource = src.resolve("p").resolve("resource.properties");
+        Files.createDirectories(resource.getParent());
+        Files.newOutputStream(resource).close();
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .sourcepath(src.toString())
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+        if (!log.equals(""))
+            throw new Exception("expected output not found, actual output: " + log);
+    }
 }
diff --git a/langtools/test/tools/javac/modules/RequiresStaticTest.java b/langtools/test/tools/javac/modules/RequiresStaticTest.java
new file mode 100644
index 0000000..5a96bb2
--- /dev/null
+++ b/langtools/test/tools/javac/modules/RequiresStaticTest.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8161906 8161596
+ * @summary tests for "requires static"
+ * @library /tools/lib
+ * @modules
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main RequiresStaticTest
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import toolbox.JavaTask;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.OutputKind;
+
+public class RequiresStaticTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        RequiresStaticTest t = new RequiresStaticTest();
+        t.runTests();
+    }
+
+    @Test
+    public void testJavaSE_OK(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires static java.se; }",
+                "import java.awt.Frame;\n"  // in java.se
+                + "class Test {\n"
+                + "    Frame f;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testJavaSE_Fail(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                "module m { requires static java.se; }",
+                "import com.sun.source.tree.Tree;\n" // not in java.se (in jdk.compiler)
+                + "class Test {\n"
+                + "    Tree t;\n"
+                + "}");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics")
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("Test.java:1:27: compiler.err.doesnt.exist: com.sun.source.tree"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    public void testComplex_OK(Path base) throws Exception {
+        Path src = getComplexSrc(base, "", "");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testComplex_Fail(Path base) throws Exception {
+        Path src = getComplexSrc(base,
+                "import p5.C5; import p6.C6; import p7.C7; import p8.C8;\n",
+                "C5 c5; C6 c6; C7 c7; C8 c8;\n");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                        "--module-source-path", src.toString())
+                .files(findJavaFiles(src))
+                .outdir(classes)
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        String[] expect = {
+            "C1.java:5:10: compiler.err.not.def.access.package.cant.access: p5.C5, p5",
+            "C1.java:5:24: compiler.err.not.def.access.package.cant.access: p6.C6, p6",
+            "C1.java:5:38: compiler.err.not.def.access.package.cant.access: p7.C7, p7",
+            "C1.java:5:52: compiler.err.not.def.access.package.cant.access: p8.C8, p8",
+            "C1.java:8:1: compiler.err.cant.resolve.location: kindname.class, C5, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:8: compiler.err.cant.resolve.location: kindname.class, C6, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:15: compiler.err.cant.resolve.location: kindname.class, C7, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)",
+            "C1.java:8:22: compiler.err.cant.resolve.location: kindname.class, C8, , , "
+                + "(compiler.misc.location: kindname.class, p1.C1, null)"
+        };
+
+        for (String e: expect) {
+            if (!log.contains(e))
+                throw new Exception("expected output not found: " + e);
+        }
+    }
+
+    /*
+     * Set up the following module graph
+     *     m1 -> m2 => m3 -=-> m4 --> m5
+     *            \           /
+     *              \       /
+     *                v   v
+     *                  m6 => m7 --> m8
+     * where -> is requires, => is requires transitive, --> is requires static, -=-> is requires transitive static
+     */
+    Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
+        Path src = base.resolve("src");
+
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                "module m1 { requires m2; }",
+                "package p1;\n"
+                + "import p2.C2;\n"
+                + "import p3.C3;\n"
+                + "import p4.C4;\n"
+                + m1_extraImports
+                + "class C1 {\n"
+                + "  C2 c2; C3 c3; C4 c4;\n"
+                + m1_extraUses
+                + "}\n");
+
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                "module m2 {\n"
+                + "  requires transitive m3;\n"
+                + "  requires static m6;\n"
+                + "  exports p2;\n"
+                + "}",
+                "package p2;\n"
+                + "public class C2 {p7.C7 c7; p6.C6 c6; p4.C4 c4;}\n");
+
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                "module m3 { requires transitive static m4; exports p3; }",
+                "package p3;\n"
+                + "public class C3 { }\n");
+
+        Path src_m4 = src.resolve("m4");
+        tb.writeJavaFiles(src_m4,
+                "module m4 { requires m5; requires static m6; exports p4; }",
+                "package p4;\n"
+                + "public class C4 { p6.C6 c6; p7.C7 c7;}\n");
+
+        Path src_m5 = src.resolve("m5");
+        tb.writeJavaFiles(src_m5,
+                "module m5 { exports p5; }",
+                "package p5;\n"
+                + "public class C5 { }\n");
+
+        Path src_m6 = src.resolve("m6");
+        tb.writeJavaFiles(src_m6,
+                "module m6 { requires transitive m7; exports p6; }",
+                "package p6;\n"
+                + "public class C6 { p7.C7 c7; }\n");
+
+        Path src_m7 = src.resolve("m7");
+        tb.writeJavaFiles(src_m7,
+                "module m7 { requires static m8; exports p7; }",
+                "package p7;\n"
+                + "public class C7 { p8.C8 c8; }\n");
+
+        Path src_m8 = src.resolve("m8");
+        tb.writeJavaFiles(src_m8,
+                "module m8 { exports p8; }",
+                "package p8;\n"
+                        + "public class C8 { }\n");
+
+        return src;
+    }
+
+    @Test
+    public void testRequiresStatic(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        tb.writeJavaFiles(m1,
+                "module m1 { exports m1; }",
+                "package m1;" +
+                "public class Api { }\n");
+
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        Files.createDirectories(m1Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .files(findJavaFiles(m1))
+                .outdir(m1Classes)
+                .run()
+                .writeAll();
+
+        Path m3 = src.resolve("m3");
+        tb.writeJavaFiles(m3,
+                "module m3 { requires static m1; }",
+                "package m3;\n" +
+                "public class Test {\n" +
+                "    public static void main(String... args) {\n" +
+                "        try {\n" +
+                "           Class.forName(\"m1.Api\");\n" +
+                "        } catch (ClassNotFoundException e) {\n" +
+                "            System.err.println(\"ok\");\n" +
+                "        }\n" +
+                "    }\n" +
+                "}",
+                "package m3;\n" +
+                "public class ApiUse{\n" +
+                "    m1.Api api;\n" +
+                "}");
+
+        Path m3Classes = classes.resolve("m3");
+        Files.createDirectories(m3Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-path", m1Classes.toString())
+                .files(findJavaFiles(m3))
+                .outdir(m3Classes)
+                .run()
+                .writeAll();
+
+        String log = new JavaTask(tb)
+                .vmOptions("--module-path", m3Classes.toString(), "--add-modules", "m3")
+                .className("m3.Test")
+                .run()
+                .writeAll()
+                .getOutput(OutputKind.STDERR);
+
+        String expected = "ok" + System.getProperty("line.separator");
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    public void testRequiresTransitiveStatic(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        tb.writeJavaFiles(m1,
+                "module m1 { exports m1; }",
+                "package m1;" +
+                "public class Api { }\n");
+
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        Files.createDirectories(m1Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .files(findJavaFiles(m1))
+                .outdir(m1Classes)
+                .run()
+                .writeAll();
+
+        Path m2 = src.resolve("m2");
+        tb.writeJavaFiles(m2,
+                "module m2 { requires transitive static m1; }");
+
+        Path m2Classes = classes.resolve("m2");
+        Files.createDirectories(m2Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-path", m1Classes.toString())
+                .files(findJavaFiles(m2))
+                .outdir(m2Classes)
+                .run()
+                .writeAll();
+
+        Path m3 = src.resolve("m3");
+        tb.writeJavaFiles(m3,
+                "module m3 { requires m2; }",
+                "package m3;\n" +
+                "public class Test {\n" +
+                "    public static void main(String... args) {\n" +
+                "        try {\n" +
+                "           Class.forName(\"m1.Api\");\n" +
+                "        } catch (ClassNotFoundException e) {\n" +
+                "            System.err.println(\"ok\");\n" +
+                "        }\n" +
+                "    }\n" +
+                "}",
+                "package m3;\n" +
+                "public class ApiUse{\n" +
+                "    m1.Api api;\n" +
+                "}");
+
+        Path m3Classes = classes.resolve("m3");
+        Files.createDirectories(m3Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-path", m1Classes.toString() + File.pathSeparator + m2Classes.toString())
+                .files(findJavaFiles(m3))
+                .outdir(m3Classes)
+                .run()
+                .writeAll();
+
+        String log = new JavaTask(tb)
+                .vmOptions("--module-path", m2Classes.toString() + File.pathSeparator + m3Classes.toString(),
+                           "--add-modules", "m3")
+                .className("m3.Test")
+                .run()
+                .writeAll()
+                .getOutput(OutputKind.STDERR);
+
+        String expected = "ok" + System.getProperty("line.separator");
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    public void testRequiresStaticTransitive(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path m1 = src.resolve("m1");
+        tb.writeJavaFiles(m1,
+                "module m1 { exports m1; }",
+                "package m1;" +
+                "public class Api { }\n");
+
+        Path classes = base.resolve("classes");
+        Path m1Classes = classes.resolve("m1");
+        Files.createDirectories(m1Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .files(findJavaFiles(m1))
+                .outdir(m1Classes)
+                .run()
+                .writeAll();
+
+        Path m2 = src.resolve("m2");
+        tb.writeJavaFiles(m2,
+                "module m2 { requires transitive static m1; }");
+
+        Path m2Classes = classes.resolve("m2");
+        Files.createDirectories(m2Classes);
+
+        new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-path", m1Classes.toString())
+                .files(findJavaFiles(m2))
+                .outdir(m2Classes)
+                .run()
+                .writeAll();
+    }
+}
diff --git a/langtools/test/tools/javac/modules/RequiresPublicTest.java b/langtools/test/tools/javac/modules/RequiresTransitiveTest.java
similarity index 93%
rename from langtools/test/tools/javac/modules/RequiresPublicTest.java
rename to langtools/test/tools/javac/modules/RequiresTransitiveTest.java
index 68184db..44e1c24 100644
--- a/langtools/test/tools/javac/modules/RequiresPublicTest.java
+++ b/langtools/test/tools/javac/modules/RequiresTransitiveTest.java
@@ -23,13 +23,13 @@
 
 /*
  * @test
- * @summary tests for "requires public"
+ * @summary tests for "requires transitive"
  * @library /tools/lib
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
  *      jdk.compiler/com.sun.tools.javac.main
  * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
- * @run main RequiresPublicTest
+ * @run main RequiresTransitiveTest
  */
 
 import java.nio.file.Files;
@@ -39,10 +39,10 @@
 import toolbox.Task;
 import toolbox.ToolBox;
 
-public class RequiresPublicTest extends ModuleTestBase {
+public class RequiresTransitiveTest extends ModuleTestBase {
 
     public static void main(String... args) throws Exception {
-        RequiresPublicTest t = new RequiresPublicTest();
+        RequiresTransitiveTest t = new RequiresTransitiveTest();
         t.runTests();
     }
 
@@ -142,7 +142,7 @@
      * Set up the following module graph
      *     m1 -> m2 => m3 => m4 -> m5
      *              -> m6 => m7
-     * where -> is requires, => is requires public
+     * where -> is requires, => is requires transitive
      */
     Path getComplexSrc(Path base, String m1_extraImports, String m1_extraUses) throws Exception {
         Path src = base.resolve("src");
@@ -163,7 +163,7 @@
         Path src_m2 = src.resolve("m2");
         tb.writeJavaFiles(src_m2,
                 "module m2 {\n"
-                + "  requires public m3;\n"
+                + "  requires transitive m3;\n"
                 + "  requires        m6;\n"
                 + "  exports p2;\n"
                 + "}",
@@ -172,7 +172,7 @@
 
         Path src_m3 = src.resolve("m3");
         tb.writeJavaFiles(src_m3,
-                "module m3 { requires public m4; exports p3; }",
+                "module m3 { requires transitive m4; exports p3; }",
                 "package p3;\n"
                 + "public class C3 { }\n");
 
@@ -190,7 +190,7 @@
 
         Path src_m6 = src.resolve("m6");
         tb.writeJavaFiles(src_m6,
-                "module m6 { requires public m7; exports p6; }",
+                "module m6 { requires transitive m7; exports p6; }",
                 "package p6;\n"
                 + "public class C6 { }\n");
 
diff --git a/langtools/test/tools/javac/modules/T8158224/Processor.java b/langtools/test/tools/javac/modules/T8158224/Processor.java
index abcc222..6b8b717 100644
--- a/langtools/test/tools/javac/modules/T8158224/Processor.java
+++ b/langtools/test/tools/javac/modules/T8158224/Processor.java
@@ -37,4 +37,4 @@
     public boolean process(Set<? extends TypeElement> tE, RoundEnvironment env) {
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/langtools/test/tools/javac/modules/T8168854/pack1/Outer.java b/langtools/test/tools/javac/modules/T8168854/pack1/Outer.java
index ff272d5..1f3ab6a 100644
--- a/langtools/test/tools/javac/modules/T8168854/pack1/Outer.java
+++ b/langtools/test/tools/javac/modules/T8168854/pack1/Outer.java
@@ -28,4 +28,4 @@
 public class Outer {
     public class Inter {
     }
-}
\ No newline at end of file
+}
diff --git a/langtools/test/tools/javac/modules/T8168854/pack1/Outer1.java b/langtools/test/tools/javac/modules/T8168854/pack1/Outer1.java
index 2710e62..6b9a507 100644
--- a/langtools/test/tools/javac/modules/T8168854/pack1/Outer1.java
+++ b/langtools/test/tools/javac/modules/T8168854/pack1/Outer1.java
@@ -31,4 +31,4 @@
             new Outer().super();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/langtools/test/tools/javac/options/release/ReleaseOptionClashes.java b/langtools/test/tools/javac/options/release/ReleaseOptionClashes.java
index 1fb6820..e7e553c 100644
--- a/langtools/test/tools/javac/options/release/ReleaseOptionClashes.java
+++ b/langtools/test/tools/javac/options/release/ReleaseOptionClashes.java
@@ -25,7 +25,7 @@
  * @test
  * @bug 8072480
  * @summary Verify option clash between --release and -source is reported correctly.
- * @modules jdk.compiler/com.sun.tools.javac.util
+ * @modules jdk.compiler/com.sun.tools.javac.util:open
  */
 
 import java.io.ByteArrayOutputStream;
diff --git a/langtools/test/tools/javac/parser/JavacParserTest.java b/langtools/test/tools/javac/parser/JavacParserTest.java
index 05fced2..43e8d31 100644
--- a/langtools/test/tools/javac/parser/JavacParserTest.java
+++ b/langtools/test/tools/javac/parser/JavacParserTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -370,7 +370,7 @@
     }
 
     @Test
-    void testCorrectWilcardPositions1() throws IOException {
+    void testCorrectWildcardPositions1() throws IOException {
         performWildcardPositionsTest("package test; import java.util.List; " +
                 "class Test { private void method() { List<? extends List<? extends String>> l; } }",
 
@@ -385,7 +385,7 @@
     }
 
     @Test
-    void testCorrectWilcardPositions2() throws IOException {
+    void testCorrectWildcardPositions2() throws IOException {
         performWildcardPositionsTest("package test; import java.util.List; "
                 + "class Test { private void method() { List<? super List<? super String>> l; } }",
                 Arrays.asList("List<? super List<? super String>> l;",
@@ -399,7 +399,7 @@
     }
 
     @Test
-    void testCorrectWilcardPositions3() throws IOException {
+    void testCorrectWildcardPositions3() throws IOException {
         performWildcardPositionsTest("package test; import java.util.List; " +
                 "class Test { private void method() { List<? super List<?>> l; } }",
 
@@ -413,7 +413,7 @@
     }
 
     @Test
-    void testCorrectWilcardPositions4() throws IOException {
+    void testCorrectWildcardPositions4() throws IOException {
         performWildcardPositionsTest("package test; import java.util.List; " +
                 "class Test { private void method() { " +
                 "List<? extends List<? extends List<? extends String>>> l; } }",
@@ -432,7 +432,7 @@
     }
 
     @Test
-    void testCorrectWilcardPositions5() throws IOException {
+    void testCorrectWildcardPositions5() throws IOException {
         performWildcardPositionsTest("package test; import java.util.List; " +
                 "class Test { private void method() { " +
                 "List<? extends List<? extends List<? extends String   >>> l; } }",
@@ -701,7 +701,7 @@
             }
         }.scan(cut, null);
 
-        assertEquals("testSwitchError: The Erroneous tree "
+        assertEquals("testOperatorMissingError: The Erroneous tree "
                 + "error values: " + values
                 + " do not match expected error values: "
                 + expectedValues, values, expectedValues);
@@ -726,7 +726,7 @@
             }
         }.scan(cut, null);
 
-        assertEquals("testSwitchError: The Erroneous tree "
+        assertEquals("testMissingParenthesisError: The Erroneous tree "
                 + "error values: " + values
                 + " do not match expected error values: "
                 + expectedValues, values, expectedValues);
@@ -751,7 +751,7 @@
             }
         }.scan(cut, null);
 
-        assertEquals("testSwitchError: The Erroneous tree "
+        assertEquals("testMissingClassError: The Erroneous tree "
                 + "error values: " + values
                 + " do not match expected error values: "
                 + expectedValues, values, expectedValues);
diff --git a/langtools/test/tools/javac/platform/PlatformProviderTest.java b/langtools/test/tools/javac/platform/PlatformProviderTest.java
index 2481d02..9ff0c23 100644
--- a/langtools/test/tools/javac/platform/PlatformProviderTest.java
+++ b/langtools/test/tools/javac/platform/PlatformProviderTest.java
@@ -30,7 +30,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.platform
- *          jdk.compiler/com.sun.tools.javac.util
+ *          jdk.compiler/com.sun.tools.javac.util:+open
  * @build toolbox.ToolBox PlatformProviderTest
  * @run main/othervm PlatformProviderTest
  */
@@ -99,7 +99,7 @@
                   .outdir(".")
                   .options("-J--class-path=" + System.getProperty("test.classes"),
                            "-J--add-exports=jdk.compiler/com.sun.tools.javac.platform=ALL-UNNAMED",
-                           "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                           "-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
                            "-XDrawDiagnostics",
                            "--release",
                            platformSpec,
@@ -134,7 +134,7 @@
                   .outdir(".")
                   .options("-J--class-path=" + System.getProperty("test.classes"),
                            "-J--add-exports=jdk.compiler/com.sun.tools.javac.platform=ALL-UNNAMED",
-                           "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                           "-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
                            "--release",
                            "fail",
                            System.getProperty("test.src") + "/PlatformProviderTestSource.java")
diff --git a/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java b/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java
index 9f8a397..a753057 100644
--- a/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java
+++ b/langtools/test/tools/javac/processing/model/LocalClasses/LocalClassesModel.java
@@ -70,4 +70,4 @@
     public SourceVersion getSupportedSourceVersion() {
         return SourceVersion.latestSupported();
     }
-}
\ No newline at end of file
+}
diff --git a/langtools/test/tools/javac/processing/model/LocalInAnonymous.java b/langtools/test/tools/javac/processing/model/LocalInAnonymous.java
new file mode 100644
index 0000000..6cbbe51
--- /dev/null
+++ b/langtools/test/tools/javac/processing/model/LocalInAnonymous.java
@@ -0,0 +1,267 @@
+/*
+ * 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 8166628
+ * @summary Verify that loading a classfile for a local class that is a member of an anonymous class
+ *          won't break compilation.
+ * @modules jdk.compiler
+ */
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+import com.sun.source.tree.BlockTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+
+public class LocalInAnonymous {
+
+    public static void main(String[] args) throws Exception {
+        Path base = Paths.get(".").toAbsolutePath();
+        Path classes = base.resolve("classes");
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        DiagnosticListener<JavaFileObject> noErrors = d -> {
+            if (d.getKind() == Diagnostic.Kind.ERROR) {
+                throw new AssertionError(d.getMessage(null));
+            }
+        };
+        List<TJFO> files = Arrays.asList(new TJFO("Test", CODE));
+        List<String> options = Arrays.asList("-d", classes.toString());
+        StringWriter out = new StringWriter();
+        JavacTask task = (JavacTask) compiler.getTask(out, null, noErrors, options, null, files);
+        task.call();
+        if (!out.toString().isEmpty()) {
+            throw new AssertionError("Unexpected output: " + out);
+        }
+        options = Arrays.asList("-classpath", classes.toString(), "-d", classes.toString());
+        JavacTask task2 = (JavacTask) compiler.getTask(out, null, noErrors, options, null, files);
+        task2.addTaskListener(new TaskListener() {
+            @Override
+            public void started(TaskEvent te) {
+            }
+            @Override
+            public void finished(TaskEvent te) {
+                if (te.getKind() == Kind.ENTER) {
+                    Element pack = task2.getElements().getTypeElement("Test").getEnclosingElement();
+                    System.err.println(pack.getEnclosedElements());
+                }
+                if (te.getKind() == Kind.ANALYZE) {
+                    PackageElement pack = task2.getElements().getPackageOf(te.getTypeElement());
+                    new OwnerCheck(Trees.instance(task2), pack).scan(te.getCompilationUnit(), null);
+                }
+            }
+        });
+        task2.call();
+        if (!out.toString().isEmpty()) {
+            throw new AssertionError("Unexpected output: " + out);
+        }
+        options = Arrays.asList("-classpath", classes.toString(),
+                                "-d", classes.toString(),
+                                "-processorpath", System.getProperty("test.classes"),
+                                "-processor", Processor.class.getName());
+        JavacTask task3 = (JavacTask) compiler.getTask(out, null, noErrors, options, null, files);
+        task3.call();
+        if (!out.toString().isEmpty()) {
+            throw new AssertionError("Unexpected output: " + out);
+        }
+    }
+
+    private static final class TJFO extends SimpleJavaFileObject {
+
+        private final String code;
+
+        public TJFO(String name, String code) throws URISyntaxException {
+            super(new URI("mem:///" + name + ".java"), Kind.SOURCE);
+            this.code = code;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            return code;
+        }
+
+    }
+
+    @SupportedAnnotationTypes("*")
+    public static final class Processor extends AbstractProcessor {
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+            Trees trees = Trees.instance(processingEnv);
+            Elements elements = processingEnv.getElementUtils();
+            Element pack = elements.getTypeElement("Test").getEnclosingElement();
+            for (Element root : pack.getEnclosedElements()) {
+                TreePath tp = trees.getPath(root);
+                new OwnerCheck(trees, pack).scan(tp.getCompilationUnit(), null);
+
+            }
+            return false;
+        }
+
+    }
+
+    private static final class OwnerCheck extends TreePathScanner<Void, Void> {
+        private final Trees trees;
+        private Element currentOwner;
+
+        public OwnerCheck(Trees trees, Element pack) {
+            this.trees = trees;
+            this.currentOwner = pack;
+        }
+
+        @Override
+        public Void visitClass(ClassTree node, Void p) {
+            Element prevOwner = currentOwner;
+            try {
+                Element currentElement = trees.getElement(getCurrentPath());
+                if (currentOwner != null && currentElement.getEnclosingElement() != currentOwner) {
+                    throw new AssertionError("Unexpected owner!");
+                }
+                currentOwner = currentElement;
+                return super.visitClass(node, p);
+            } finally {
+                currentOwner = prevOwner;
+            }
+        }
+
+        @Override
+        public Void visitMethod(MethodTree node, Void p) {
+            Element prevOwner = currentOwner;
+            try {
+                Element currentElement = trees.getElement(getCurrentPath());
+                if (currentElement.getEnclosingElement() != currentOwner) {
+                    throw new AssertionError("Unexpected owner!");
+                }
+                currentOwner = currentElement;
+                return super.visitMethod(node, p);
+            } finally {
+                currentOwner = prevOwner;
+            }
+        }
+
+        @Override
+        public Void visitVariable(VariableTree node, Void p) {
+            Element currentElement = trees.getElement(getCurrentPath());
+            if (!currentElement.getKind().isField()) {
+                return super.visitVariable(node, p);
+            }
+            Element prevOwner = currentOwner;
+            try {
+                if (currentElement.getEnclosingElement() != currentOwner) {
+                    throw new AssertionError("Unexpected owner!");
+                }
+                currentOwner = currentElement;
+                return super.visitVariable(node, p);
+            } finally {
+                currentOwner = prevOwner;
+            }
+        }
+
+        @Override
+        public Void visitBlock(BlockTree node, Void p) {
+            if (getCurrentPath().getParentPath().getLeaf().getKind() != Tree.Kind.CLASS) {
+                return super.visitBlock(node, p);
+            }
+            Element prevOwner = currentOwner;
+            try {
+                currentOwner = null;
+                return super.visitBlock(node, p);
+            } finally {
+                currentOwner = prevOwner;
+            }
+        }
+
+    }
+
+    private static final String CODE =
+            "public class Test {\n" +
+            "   void test() {\n" +
+            "       Object o = new Object() {\n" +
+            "           class IC {}\n" +
+            "           public Object get() {\n" +
+            "               return new IC();\n" +
+            "           }\n" +
+            "       };\n" +
+            "   }\n" +
+            "   {\n" +
+            "       Object o = new Object() {\n" +
+            "           class IC {}\n" +
+            "           public Object get() {\n" +
+            "               return new IC();\n" +
+            "           }\n" +
+            "       };\n" +
+            "   }\n" +
+            "   static {\n" +
+            "       Object o = new Object() {\n" +
+            "           class IC {}\n" +
+            "           public Object get() {\n" +
+            "               return new IC();\n" +
+            "           }\n" +
+            "       };\n" +
+            "   }\n" +
+            "   Object o1 = new Object() {\n" +
+            "       class IC {}\n" +
+            "       public Object get() {\n" +
+            "          return new IC();\n" +
+            "       }\n" +
+            "   };\n" +
+            "   static Object o2 = new Object() {\n" +
+            "       class IC {}\n" +
+            "       public Object get() {\n" +
+            "          return new IC();\n" +
+            "       }\n" +
+            "   };\n" +
+            "}";
+}
diff --git a/langtools/test/tools/javac/processing/model/TestSymtabItems.java b/langtools/test/tools/javac/processing/model/TestSymtabItems.java
index 3872052..e1f8068 100644
--- a/langtools/test/tools/javac/processing/model/TestSymtabItems.java
+++ b/langtools/test/tools/javac/processing/model/TestSymtabItems.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 7021183 7025809
  * @summary 269: assertion failure getting enclosing element of an undefined name
- * @modules jdk.compiler/com.sun.tools.javac.code
+ * @modules jdk.compiler/com.sun.tools.javac.code:+open
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.compiler/com.sun.tools.javac.model
diff --git a/langtools/test/tools/javac/scope/DupUnsharedTest.java b/langtools/test/tools/javac/scope/DupUnsharedTest.java
index 309cd94..6eff753 100644
--- a/langtools/test/tools/javac/scope/DupUnsharedTest.java
+++ b/langtools/test/tools/javac/scope/DupUnsharedTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 /*
  * @test
  * @summary WriteableScope.dupUnshared not working properly for shared Scopes.
- * @modules jdk.compiler/com.sun.tools.javac.code
+ * @modules jdk.compiler/com.sun.tools.javac.code:+open
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.util
  */
diff --git a/langtools/test/tools/javac/scope/HashCollisionTest.java b/langtools/test/tools/javac/scope/HashCollisionTest.java
index 1793799..b22b43e 100644
--- a/langtools/test/tools/javac/scope/HashCollisionTest.java
+++ b/langtools/test/tools/javac/scope/HashCollisionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @summary Ensure Scope impl can cope with hash collisions
  * @library /tools/javac/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
- *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.code:+open
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.tree
  *          jdk.compiler/com.sun.tools.javac.util
diff --git a/langtools/test/tools/javac/scope/IterateAndRemove.java b/langtools/test/tools/javac/scope/IterateAndRemove.java
index fab5ea5..f560b8f 100644
--- a/langtools/test/tools/javac/scope/IterateAndRemove.java
+++ b/langtools/test/tools/javac/scope/IterateAndRemove.java
@@ -103,4 +103,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/langtools/test/tools/javac/tree/SourceTreeScannerTest.java b/langtools/test/tools/javac/tree/SourceTreeScannerTest.java
index 1d1bc2c..dd16b5a 100644
--- a/langtools/test/tools/javac/tree/SourceTreeScannerTest.java
+++ b/langtools/test/tools/javac/tree/SourceTreeScannerTest.java
@@ -53,6 +53,7 @@
 import com.sun.source.util.TreeScanner;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
 import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
 import com.sun.tools.javac.util.List;
 
@@ -145,7 +146,13 @@
                     }
                     try {
                         //System.err.println("FIELD: " + f.getName());
-                        reflectiveScan(f.get(tree));
+                        if (tree instanceof JCModuleDecl && f.getName().equals("mods")) {
+                            // The modifiers will not found by TreeScanner,
+                            // but the embedded annotations will be.
+                            reflectiveScan(((JCModuleDecl) tree).mods.annotations);
+                        } else {
+                            reflectiveScan(f.get(tree));
+                        }
                     } catch (IllegalAccessException e) {
                         error(e.toString());
                     }
diff --git a/langtools/test/tools/javac/tree/TreeKindTest.java b/langtools/test/tools/javac/tree/TreeKindTest.java
index e285e44..518190d 100644
--- a/langtools/test/tools/javac/tree/TreeKindTest.java
+++ b/langtools/test/tools/javac/tree/TreeKindTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -114,6 +114,14 @@
                 ok = ok & verify(k, i, i == AnnotationTree.class);
                 break;
 
+            case EXPORTS:
+                ok = ok & verify(k, i, i == ExportsTree.class);
+                break;
+
+            case OPENS:
+                ok = ok & verify(k, i, i == OpensTree.class);
+                break;
+
             case OTHER:
                 ok = ok & verify(k, i, i == null);
                 break;
diff --git a/langtools/test/tools/javac/types/ScopeListenerTest.java b/langtools/test/tools/javac/types/ScopeListenerTest.java
index 9173ac4..cd12fba 100644
--- a/langtools/test/tools/javac/types/ScopeListenerTest.java
+++ b/langtools/test/tools/javac/types/ScopeListenerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
  * @bug 8039262
  * @summary Ensure that using Types.membersClosure does not increase the number of listeners on the
  *          class's members Scope.
- * @modules jdk.compiler/com.sun.tools.javac.code
+ * @modules jdk.compiler/com.sun.tools.javac.code:+open
  *          jdk.compiler/com.sun.tools.javac.file
  *          jdk.compiler/com.sun.tools.javac.util
  */
diff --git a/langtools/test/tools/javap/4870651/T4870651.java b/langtools/test/tools/javap/4870651/T4870651.java
index 73e8851..dd1536d 100644
--- a/langtools/test/tools/javap/4870651/T4870651.java
+++ b/langtools/test/tools/javap/4870651/T4870651.java
@@ -46,8 +46,8 @@
                "v1(java.lang.String...)");
 
         verify("Test$Enum",
-               "flags: ACC_FINAL, ACC_SUPER, ACC_ENUM",
-               "flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM");
+               "flags: (0x4030) ACC_FINAL, ACC_SUPER, ACC_ENUM",
+               "flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM");
 
         if (errors > 0)
             throw new Error(errors + " found.");
diff --git a/langtools/test/tools/javap/MethodParameters.java b/langtools/test/tools/javap/MethodParameters.java
index 6052f63..aed82fc 100644
--- a/langtools/test/tools/javap/MethodParameters.java
+++ b/langtools/test/tools/javap/MethodParameters.java
@@ -45,7 +45,7 @@
     static final String Init0_expected =
         ("  Foo();\n" +
          "    descriptor: ()V\n" +
-         "    flags:\n" +
+         "    flags: (0x0000)\n" +
          "    Code:\n" +
          "      stack=1, locals=1, args_size=1\n" +
          "         0: aload_0\n" +
@@ -57,7 +57,7 @@
     static final String Init1_expected =
         ("  Foo(int);\n" +
          "    descriptor: (I)V\n" +
-         "    flags:\n" +
+         "    flags: (0x0000)\n" +
          "    Code:\n" +
          "      stack=1, locals=2, args_size=2\n" +
          "         0: aload_0\n" +
@@ -72,7 +72,7 @@
     static final String foo0_expected =
         ("  void foo0();\n" +
          "    descriptor: ()V\n" +
-         "    flags:\n" +
+         "    flags: (0x0000)\n" +
          "    Code:\n" +
          "      stack=0, locals=1, args_size=1\n" +
          "         0: return\n" +
@@ -82,7 +82,7 @@
     static final String foo2_expected =
         ("  void foo2(int, int);\n" +
          "    descriptor: (II)V\n" +
-         "    flags:\n" +
+         "    flags: (0x0000)\n" +
          "    Code:\n" +
          "      stack=0, locals=3, args_size=3\n" +
          "         0: return\n" +
diff --git a/langtools/test/tools/javap/T4975569.java b/langtools/test/tools/javap/T4975569.java
index ae117c6..c43598b 100644
--- a/langtools/test/tools/javap/T4975569.java
+++ b/langtools/test/tools/javap/T4975569.java
@@ -42,12 +42,12 @@
     }
 
     void run() {
-        verify(Anno.class.getName(), "flags: ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION");
-        verify(E.class.getName(),    "flags: ACC_FINAL, ACC_SUPER, ACC_ENUM");
-        verify(S.class.getName(),    "flags: ACC_BRIDGE, ACC_SYNTHETIC",
+        verify(Anno.class.getName(), "flags: \\(0x2600\\) ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION");
+        verify(E.class.getName(),    "flags: \\(0x4030\\) ACC_FINAL, ACC_SUPER, ACC_ENUM");
+        verify(S.class.getName(),    "flags: \\(0x1040\\) ACC_BRIDGE, ACC_SYNTHETIC",
                                      "InnerClasses:\n  static [# =\\w]+; +// ");
         verify(V.class.getName(),    "void m\\(java.lang.String...\\)",
-                                     "flags: ACC_VARARGS");
+                                     "flags: \\(0x0080\\) ACC_VARARGS");
         verify(Prot.class.getName(), "InnerClasses:\n  protected [# =\\w]+; +// ");
         verify(Priv.class.getName(), new String[]{"-p"},
                                      "InnerClasses:\n  private [# =\\w]+; +// ");
diff --git a/langtools/test/tools/jdeps/lib/ModuleMetaData.java b/langtools/test/tools/jdeps/lib/ModuleMetaData.java
index f37c3a7..3ae3cdd 100644
--- a/langtools/test/tools/jdeps/lib/ModuleMetaData.java
+++ b/langtools/test/tools/jdeps/lib/ModuleMetaData.java
@@ -70,8 +70,8 @@
         return this;
     }
 
-    ModuleMetaData requiresPublic(String name) {
-        requires.put(name, new ModuleRequires(name, PUBLIC));
+    ModuleMetaData requiresTransitive(String name) {
+        requires.put(name, new ModuleRequires(name, TRANSITIVE));
         return this;
     }
 
diff --git a/langtools/test/tools/jdeps/modules/CheckModuleTest.java b/langtools/test/tools/jdeps/modules/CheckModuleTest.java
index 2b7bea5..96a6d1f 100644
--- a/langtools/test/tools/jdeps/modules/CheckModuleTest.java
+++ b/langtools/test/tools/jdeps/modules/CheckModuleTest.java
@@ -54,7 +54,7 @@
 
     // m4 and m5 are analyzed.  Others are compiled to make sure they are present
     // on the module path for analysis
-    private static final Set<String> modules = Set.of("unsafe", "m4", "m5", "m6", "m7", "m8");
+    private static final Set<String> modules = Set.of("unsafe", "m4", "m5", "mVI", "mVII", "m8");
 
     private static final String JAVA_BASE = "java.base";
 
@@ -100,10 +100,10 @@
             { "m4", new ModuleMetaData[] {
                         // original
                         new ModuleMetaData("m4")
-                            .requiresPublic("java.compiler")
+                            .requiresTransitive("java.compiler")
                             .requires("java.logging")
                             // unnused exports
-                            .exports("p4.internal", Set.of("m6", "m7")),
+                            .exports("p4.internal", Set.of("mVI", "mVII")),
                         // suggested version
                         new ModuleMetaData("m4")
                             .requires("java.compiler"),
@@ -115,21 +115,21 @@
             { "m5", new ModuleMetaData[] {
                         // original
                         new ModuleMetaData("m5")
-                            .requiresPublic("java.compiler")
-                            .requiresPublic("java.logging")
+                            .requiresTransitive("java.compiler")
+                            .requiresTransitive("java.logging")
                             .requires("java.sql")
-                            .requiresPublic("m4"),
+                            .requiresTransitive("m4"),
                         // suggested version
                         new ModuleMetaData("m5")
-                            .requiresPublic("java.compiler")
+                            .requiresTransitive("java.compiler")
                             .requires("java.logging")
-                            .requiresPublic("java.sql")
-                            .requiresPublic("m4"),
+                            .requiresTransitive("java.sql")
+                            .requiresTransitive("m4"),
                         // reduced version
                         new ModuleMetaData("m5")
-                            .requiresPublic("java.compiler")
-                            .requiresPublic("java.sql")
-                            .requiresPublic("m4"),
+                            .requiresTransitive("java.compiler")
+                            .requiresTransitive("java.sql")
+                            .requiresTransitive("m4"),
                     }
             },
         };
diff --git a/langtools/test/tools/jdeps/modules/GenModuleInfo.java b/langtools/test/tools/jdeps/modules/GenModuleInfo.java
index 22ef46d..b9e2a39 100644
--- a/langtools/test/tools/jdeps/modules/GenModuleInfo.java
+++ b/langtools/test/tools/jdeps/modules/GenModuleInfo.java
@@ -30,14 +30,17 @@
  * @run testng GenModuleInfo
  */
 
-import java.io.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
 import java.lang.module.ModuleDescriptor;
 
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import java.util.Arrays;
+import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -51,7 +54,6 @@
 public class GenModuleInfo {
     private static final String MODULE_INFO = "module-info.class";
     private static final String TEST_SRC = System.getProperty("test.src");
-    private static final String TEST_CLASSES = System.getProperty("test.classes");
 
     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
     private static final Path MODS_DIR = Paths.get("mods");
@@ -60,8 +62,85 @@
     private static final Path NEW_MODS_DIR = Paths.get("new_mods");
 
     // the names of the modules in this test
-    private static final String UNSUPPORTED = "unsupported";
-    private static String[] modules = new String[] {"m1", "m2", "m3", UNSUPPORTED};
+    public static final String UNSUPPORTED = "unsupported";
+    public static final Set<String> MODULES = Set.of(
+        "mI", "mII", "mIII", "provider", UNSUPPORTED
+    );
+
+    /**
+     * Compile modules
+     */
+    public static void compileModules(Path dest) {
+        assertTrue(CompilerUtils.compileModule(SRC_DIR, dest, UNSUPPORTED,
+            "--add-exports", "java.base/jdk.internal.perf=" + UNSUPPORTED));
+        MODULES.stream()
+               .filter(mn -> !mn.equals(UNSUPPORTED))
+               .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, dest, mn)));
+    }
+
+    /**
+     * Create JAR files with no module-info.class
+     */
+    public static List<Path> createJARFiles(Path mods, Path libs) throws IOException {
+        Files.createDirectory(libs);
+
+        for (String mn : MODULES) {
+            Path root = mods.resolve(mn);
+            Path msrc = SRC_DIR.resolve(mn);
+            Path metaInf = msrc.resolve("META-INF");
+            if (Files.exists(metaInf)) {
+                try (Stream<Path> resources = Files.find(metaInf, Integer.MAX_VALUE,
+                        (p, attr) -> { return attr.isRegularFile();})) {
+                    resources.forEach(file -> {
+                        try {
+                            Path path = msrc.relativize(file);
+                            Files.createDirectories(root.resolve(path).getParent());
+                            Files.copy(file, root.resolve(path));
+                        } catch (IOException e) {
+                            throw new UncheckedIOException(e);
+                        }
+                    });
+                }
+            }
+            // copy all entries except module-info.class
+            try (Stream<Path> stream = Files.find(root, Integer.MAX_VALUE,
+                    (p, attr) -> { return attr.isRegularFile();})) {
+                Stream<Path> entries = stream.filter(f -> {
+                    String fn = f.getFileName().toString();
+                    if (fn.endsWith(".class")) {
+                        return !fn.equals("module-info.class");
+                    } else {
+                        return true;
+                    }
+                });
+
+                JdepsUtil.createJar(libs.resolve(mn + ".jar"), root, entries);
+            }
+        }
+
+       return MODULES.stream()
+                .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * compile the generated module-info.java
+     */
+    public static void compileNewGenModuleInfo(Path source, Path dest) {
+
+        assertTrue(CompilerUtils.compileModule(source, dest, UNSUPPORTED,
+            "-p", dest.toString(),
+            "--add-exports", "java.base/jdk.internal.perf=" + UNSUPPORTED));
+
+        MODULES.stream()
+            .filter(mn -> !mn.equals(UNSUPPORTED))
+            .forEach(mn -> assertTrue(
+                CompilerUtils.compileModule(source, dest,
+                                            mn, "-p", dest.toString()))
+            );
+
+    }
+
     /**
      * Compiles all modules used by the test
      */
@@ -72,29 +151,14 @@
         CompilerUtils.cleanDir(DEST_DIR);
         CompilerUtils.cleanDir(NEW_MODS_DIR);
 
-        assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED,
-                                               "--add-exports", "java.base/jdk.internal.perf=" + UNSUPPORTED));
-        Arrays.asList("m1", "m2", "m3")
-              .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
+        compileModules(MODS_DIR);
 
-        Files.createDirectory(LIBS_DIR);
-        Files.createDirectory(DEST_DIR);
-
-        for (String mn : modules) {
-            Path root = MODS_DIR.resolve(mn);
-            try (Stream<Path> stream = Files.walk(root, Integer.MAX_VALUE)) {
-                Stream<Path> entries = stream.filter(f -> {
-                    String fn = f.getFileName().toString();
-                    return fn.endsWith(".class") && !fn.equals("module-info.class");
-                });
-                JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root, entries);
-            }
-        }
+        createJARFiles(MODS_DIR, LIBS_DIR);
     }
 
     @Test
-    public void jdeps() throws IOException {
-        Stream<String> files = Arrays.stream(modules)
+    public void automaticModules() throws IOException {
+        Stream<String> files = MODULES.stream()
                 .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
                 .map(Path::toString);
         JdepsRunner.run(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new));
@@ -102,43 +166,27 @@
 
     @Test
     public void test() throws IOException {
-        Stream<String> files = Arrays.stream(modules)
+        Files.createDirectory(DEST_DIR);
+
+        Stream<String> files = MODULES.stream()
                 .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
                 .map(Path::toString);
 
-        JdepsRunner.run(Stream.concat(Stream.of("--generate-module-info", DEST_DIR.toString()),
-                                      files).toArray(String[]::new));
+        Stream<String> options = Stream.concat(
+            Stream.of("--generate-module-info", DEST_DIR.toString()), files);
+        JdepsRunner.run(options.toArray(String[]::new));
 
         // check file exists
-        Arrays.stream(modules)
-                .map(mn -> DEST_DIR.resolve(mn).resolve("module-info.java"))
-                .forEach(f -> assertTrue(Files.exists(f)));
+        MODULES.stream()
+             .map(mn -> DEST_DIR.resolve(mn).resolve("module-info.java"))
+             .forEach(f -> assertTrue(Files.exists(f)));
 
-        // copy classes except the original module-info.class
-        try (Stream<Path> stream = Files.walk(MODS_DIR, Integer.MAX_VALUE)) {
-            stream.filter(path -> !path.getFileName().toString().equals(MODULE_INFO) &&
-                                    path.getFileName().toString().endsWith(".class"))
-                  .map(path -> MODS_DIR.relativize(path))
-                  .forEach(path -> {
-                      try {
-                          Path newFile = NEW_MODS_DIR.resolve(path);
-                          Files.createDirectories(newFile.getParent());
-                          Files.copy(MODS_DIR.resolve(path), newFile);
-                      } catch (IOException e) {
-                          throw new UncheckedIOException(e);
-                      }
-                  });
-        }
+        // copy classes to a temporary directory
+        // and then compile new module-info.java
+        copyClasses(MODS_DIR, NEW_MODS_DIR);
+        compileNewGenModuleInfo(DEST_DIR, NEW_MODS_DIR);
 
-        // compile new module-info.java
-        assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR, UNSUPPORTED,
-                        "-p", NEW_MODS_DIR.toString(), "-verbose",
-                        "--add-exports", "java.base/jdk.internal.perf=" + UNSUPPORTED));
-        Arrays.asList("m1", "m2", "m3")
-              .forEach(mn -> assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR,
-                                        mn, "-p", NEW_MODS_DIR.toString())));
-
-        for (String mn : modules) {
+        for (String mn : MODULES) {
             Path p1 = NEW_MODS_DIR.resolve(mn).resolve(MODULE_INFO);
             Path p2 = MODS_DIR.resolve(mn).resolve(MODULE_INFO);
 
@@ -150,6 +198,30 @@
         }
     }
 
+    /**
+     * Copy classes except the module-info.class to the destination directory
+     */
+    public static void copyClasses(Path from, Path dest) throws IOException {
+        try (Stream<Path> stream = Files.walk(from, Integer.MAX_VALUE)) {
+            stream.filter(path -> !path.getFileName().toString().equals(MODULE_INFO) &&
+                path.getFileName().toString().endsWith(".class"))
+                .map(path -> from.relativize(path))
+                .forEach(path -> {
+                    try {
+                        Path newFile = dest.resolve(path);
+                        Files.createDirectories(newFile.getParent());
+                        Files.copy(from.resolve(path), newFile);
+                    } catch (IOException e) {
+                        throw new UncheckedIOException(e);
+                    }
+                });
+        }
+    }
+
+    /**
+     * Verify the generated module-info.java is equivalent to module-info.class
+     * compiled from source.
+     */
     private void verify(ModuleDescriptor md1, ModuleDescriptor md2) {
         System.out.println("verifying: " + md1.name());
         assertEquals(md1.name(), md2.name());
@@ -158,6 +230,14 @@
         assertEquals(md1.exports().stream()
                                   .map(ModuleDescriptor.Exports::source)
                                   .collect(Collectors.toSet()), md2.packages());
+        if (!md1.opens().isEmpty()) {
+            throw new RuntimeException("unexpected opens: " +
+                md1.opens().stream()
+                   .map(o -> o.toString())
+                   .collect(Collectors.joining(",")));
+        }
+
+        assertEquals(md1.provides(), md2.provides());
     }
 
     private Set<String> packages(Path dir) {
diff --git a/langtools/test/tools/jdeps/modules/GenOpenModule.java b/langtools/test/tools/jdeps/modules/GenOpenModule.java
new file mode 100644
index 0000000..b45204b
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/GenOpenModule.java
@@ -0,0 +1,112 @@
+/*
+ * 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 Tests jdeps --generate-open-module option
+ * @library ../lib
+ * @build CompilerUtils JdepsUtil JdepsRunner
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng GenOpenModule
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleDescriptor;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import java.util.stream.Stream;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class GenOpenModule extends GenModuleInfo {
+    private static final String MODULE_INFO = "module-info.class";
+
+    private static final Path MODS_DIR = Paths.get("mods");
+    private static final Path LIBS_DIR = Paths.get("libs");
+    private static final Path DEST_DIR = Paths.get("moduleinfosrc");
+    private static final Path NEW_MODS_DIR = Paths.get("new_mods");
+
+    /**
+     * Compiles all modules used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+
+        compileModules(MODS_DIR);
+
+        createJARFiles(MODS_DIR, LIBS_DIR);
+    }
+
+    @Test
+    public void test() throws IOException {
+        Stream<String> files = MODULES.stream()
+                .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
+                .map(Path::toString);
+
+        Stream<String> options = Stream.concat(
+            Stream.of("--generate-open-module", DEST_DIR.toString()), files);
+        JdepsRunner.run(options.toArray(String[]::new));
+
+        // check file exists
+        MODULES.stream()
+             .map(mn -> DEST_DIR.resolve(mn).resolve("module-info.java"))
+             .forEach(f -> assertTrue(Files.exists(f)));
+
+        // copy classes to a temporary directory
+        // and then compile new module-info.java
+        copyClasses(MODS_DIR, NEW_MODS_DIR);
+        compileNewGenModuleInfo(DEST_DIR, NEW_MODS_DIR);
+
+        for (String mn : MODULES) {
+            Path p1 = NEW_MODS_DIR.resolve(mn).resolve(MODULE_INFO);
+            Path p2 = MODS_DIR.resolve(mn).resolve(MODULE_INFO);
+
+            try (InputStream in1 = Files.newInputStream(p1);
+                 InputStream in2 = Files.newInputStream(p2)) {
+                verify(ModuleDescriptor.read(in1),
+                       ModuleDescriptor.read(in2));
+            }
+        }
+    }
+
+    /*
+     * Verify the dependences
+     */
+    private void verify(ModuleDescriptor openModule, ModuleDescriptor md) {
+        System.out.println("verifying: " + openModule.name());
+        assertTrue(openModule.isOpen());
+        assertTrue(!md.isOpen());
+        assertEquals(openModule.name(), md.name());
+        assertEquals(openModule.requires(), md.requires());
+        assertTrue(openModule.exports().isEmpty());
+        assertEquals(openModule.provides(), md.provides());
+    }
+}
diff --git a/langtools/test/tools/jdeps/modules/InverseDeps.java b/langtools/test/tools/jdeps/modules/InverseDeps.java
index 884651d..b9bd916 100644
--- a/langtools/test/tools/jdeps/modules/InverseDeps.java
+++ b/langtools/test/tools/jdeps/modules/InverseDeps.java
@@ -61,7 +61,7 @@
     private static final Path LIBS_DIR = Paths.get("libs");
 
     private static final Set<String> modules = new LinkedHashSet(
-        List.of("unsafe", "m4", "m5", "m6", "m7")
+        List.of("unsafe", "m4", "m5", "mVI", "mVII")
     );
 
     /**
@@ -108,8 +108,8 @@
                 }
             },
             { "jdk.unsupported", new String[][] {
-                    new String[] {"jdk.unsupported", "unsafe", "m6", "m7"},
-                    new String[] {"jdk.unsupported", "unsafe", "m7"}
+                    new String[] {"jdk.unsupported", "unsafe", "mVI", "mVII"},
+                    new String[] {"jdk.unsupported", "unsafe", "mVII"}
                 }
             },
         };
@@ -155,8 +155,8 @@
                     }
             },
             { "sun.misc", new String[][] {
-                        new String[] {"jdk.unsupported", "unsafe", "m6", "m7"},
-                        new String[] {"jdk.unsupported", "unsafe", "m7"}
+                        new String[] {"jdk.unsupported", "unsafe", "mVI", "mVII"},
+                        new String[] {"jdk.unsupported", "unsafe", "mVII"}
                     }
             }
         };
@@ -180,13 +180,13 @@
         return new Object[][] {
             // -regex and result
             { "org.safe.Lib", new String[][] {
-                    new String[] { "unsafe", "m7"},
-                    new String[] { "unsafe", "m6", "m7"},
+                    new String[] { "unsafe", "mVII"},
+                    new String[] { "unsafe", "mVI", "mVII"},
                 }
             },
             { "java.util.logging.*|org.safe.Lib", new String[][] {
-                    new String[] { "unsafe", "m7"},
-                    new String[] { "unsafe", "m6", "m7"},
+                    new String[] { "unsafe", "mVII"},
+                    new String[] { "unsafe", "mVI", "mVII"},
                     new String[] { "java.logging", "m5"},
                 }
             }
@@ -212,18 +212,18 @@
         return new Object[][] {
             // -regex and result
             { "sun.misc.Unsafe", new String[][] {
-                    new String[] {"jdk.unsupported", "unsafe.jar", "m6.jar", "m7.jar"},
-                    new String[] {"jdk.unsupported", "unsafe.jar", "m7.jar"}
+                    new String[] {"jdk.unsupported", "unsafe.jar", "mVI.jar", "mVII.jar"},
+                    new String[] {"jdk.unsupported", "unsafe.jar", "mVII.jar"}
                 }
             },
             { "org.safe.Lib", new String[][] {
-                    new String[] { "unsafe.jar", "m7.jar"},
-                    new String[] { "unsafe.jar", "m6.jar", "m7.jar"},
+                    new String[] { "unsafe.jar", "mVII.jar"},
+                    new String[] { "unsafe.jar", "mVI.jar", "mVII.jar"},
                 }
             },
             { "java.util.logging.*|org.safe.Lib", new String[][] {
-                    new String[] { "unsafe.jar", "m7.jar"},
-                    new String[] { "unsafe.jar", "m6.jar", "m7.jar"},
+                    new String[] { "unsafe.jar", "mVII.jar"},
+                    new String[] { "unsafe.jar", "mVI.jar", "mVII.jar"},
                     new String[] { "java.logging", "m5.jar"},
                 }
             }
@@ -234,11 +234,11 @@
     public void testClassPath(String name, String[][] expected) throws Exception {
         // -classpath
         String cpath = modules.stream()
-            .filter(mn -> !mn.equals("m7"))
+            .filter(mn -> !mn.equals("mVII"))
             .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString())
             .collect(Collectors.joining(File.pathSeparator));
 
-        Path jarfile = LIBS_DIR.resolve("m7.jar");
+        Path jarfile = LIBS_DIR.resolve("mVII.jar");
 
         String cmd1 = String.format("jdeps --inverse -classpath %s -regex %s %s%n",
             cpath, name, jarfile);
diff --git a/langtools/test/tools/jdeps/modules/ModuleTest.java b/langtools/test/tools/jdeps/modules/ModuleTest.java
index 77c1367..cf58b02 100644
--- a/langtools/test/tools/jdeps/modules/ModuleTest.java
+++ b/langtools/test/tools/jdeps/modules/ModuleTest.java
@@ -58,7 +58,7 @@
 
     // the names of the modules in this test
     private static final String UNSUPPORTED = "unsupported";
-    private static String[] modules = new String[] {"m1", "m2", "m3", "m4", UNSUPPORTED};
+    private static String[] modules = new String[] {"mI", "mII", "mIII", "m4", UNSUPPORTED};
     /**
      * Compiles all modules used by the test
      */
@@ -70,37 +70,37 @@
         assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED,
                                                "--add-exports", "java.base/jdk.internal.perf=" + UNSUPPORTED));
         // m4 is not referenced
-        Arrays.asList("m1", "m2", "m3", "m4")
+        Arrays.asList("mI", "mII", "mIII", "m4")
               .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
 
-        assertTrue(CompilerUtils.compile(SRC_DIR.resolve("m3"), UNNAMED_DIR, "-p", MODS_DIR.toString()));
+        assertTrue(CompilerUtils.compile(SRC_DIR.resolve("mIII"), UNNAMED_DIR, "-p", MODS_DIR.toString()));
         Files.delete(UNNAMED_DIR.resolve("module-info.class"));
     }
 
     @DataProvider(name = "modules")
     public Object[][] expected() {
         return new Object[][]{
-                { "m3", new ModuleMetaData("m3").requiresPublic("java.sql")
-                            .requiresPublic("m2")
+                { "mIII", new ModuleMetaData("mIII").requiresTransitive("java.sql")
+                            .requiresTransitive("mII")
                             .requires("java.logging")
-                            .requiresPublic("m1")
+                            .requiresTransitive("mI")
                             .reference("p3", "java.lang", "java.base")
                             .reference("p3", "java.sql", "java.sql")
                             .reference("p3", "java.util.logging", "java.logging")
-                            .reference("p3", "p1", "m1")
-                            .reference("p3", "p2", "m2")
-                            .qualified("p3", "p2.internal", "m2")
+                            .reference("p3", "p1", "mI")
+                            .reference("p3", "p2", "mII")
+                            .qualified("p3", "p2.internal", "mII")
                 },
-                { "m2", new ModuleMetaData("m2").requiresPublic("m1")
+                { "mII", new ModuleMetaData("mII").requiresTransitive("mI")
                             .reference("p2", "java.lang", "java.base")
-                            .reference("p2", "p1", "m1")
+                            .reference("p2", "p1", "mI")
                             .reference("p2.internal", "java.lang", "java.base")
                             .reference("p2.internal", "java.io", "java.base")
                 },
-                { "m1", new ModuleMetaData("m1").requires("unsupported")
+                { "mI", new ModuleMetaData("mI").requires("unsupported")
                             .reference("p1", "java.lang", "java.base")
                             .reference("p1.internal", "java.lang", "java.base")
-                            .reference("p1.internal", "p1", "m1")
+                            .reference("p1.internal", "p1", "mI")
                             .reference("p1.internal", "q", "unsupported")
                 },
                 { "unsupported", new ModuleMetaData("unsupported")
@@ -115,7 +115,7 @@
         // jdeps --module-path mods -m <name>
         runTest(data, MODS_DIR.toString(), Set.of(name));
 
-        // jdeps --module-path libs/m1.jar:.... -m <name>
+        // jdeps --module-path libs/mI.jar:.... -m <name>
         String mp = Arrays.stream(modules)
                 .filter(mn -> !mn.equals(name))
                 .map(mn -> MODS_DIR.resolve(mn).toString())
@@ -129,21 +129,21 @@
                 { "unnamed", new ModuleMetaData("unnamed", false)
                             .depends("java.sql")
                             .depends("java.logging")
-                            .depends("m1")
-                            .depends("m2")
+                            .depends("mI")
+                            .depends("mII")
                             .reference("p3", "java.lang", "java.base")
                             .reference("p3", "java.sql", "java.sql")
                             .reference("p3", "java.util.logging", "java.logging")
-                            .reference("p3", "p1", "m1")
-                            .reference("p3", "p2", "m2")
-                            .internal("p3", "p2.internal", "m2")
+                            .reference("p3", "p1", "mI")
+                            .reference("p3", "p2", "mII")
+                            .internal("p3", "p2.internal", "mII")
                 },
         };
     }
 
     @Test(dataProvider = "unnamed")
     public void unnamedTest(String name, ModuleMetaData data) throws IOException {
-        runTest(data, MODS_DIR.toString(), Set.of("m1", "m2"), UNNAMED_DIR);
+        runTest(data, MODS_DIR.toString(), Set.of("mI", "mII"), UNNAMED_DIR);
     }
 
     private void runTest(ModuleMetaData data, String modulepath,
diff --git a/langtools/test/tools/jdeps/modules/TransitiveDeps.java b/langtools/test/tools/jdeps/modules/TransitiveDeps.java
index 2bc1f20..b5f33bd 100644
--- a/langtools/test/tools/jdeps/modules/TransitiveDeps.java
+++ b/langtools/test/tools/jdeps/modules/TransitiveDeps.java
@@ -58,7 +58,7 @@
     private static final Path LIBS_DIR = Paths.get("libs");
 
     // the names of the modules in this test
-    private static String[] modules = new String[] {"unsafe", "m6", "m7"};
+    private static String[] modules = new String[] {"unsafe", "mVI", "mVII"};
     /**
      * Compiles all modules used by the test
      */
@@ -86,15 +86,15 @@
     @DataProvider(name = "modules")
     public Object[][] expected1() {
         return new Object[][]{
-            { "m7",
-               List.of(new ModuleMetaData("m7")
-                            .requires("m6")
+            { "mVII",
+               List.of(new ModuleMetaData("mVII")
+                            .requires("mVI")
                             .requires("unsafe")
                             .reference("p7.Main", "java.lang.Object", "java.base")
                             .reference("p7.Main", "java.lang.String", "java.base")
                             .reference("p7.Main", "org.safe.Lib", "unsafe")
-                            .reference("p7.Main", "p6.safe.Lib", "m6"),
-                        new ModuleMetaData("m6")
+                            .reference("p7.Main", "p6.safe.Lib", "mVI"),
+                        new ModuleMetaData("mVI")
                             .requires("unsafe")
                             .reference("p6.indirect.UnsafeRef", "java.lang.Object", "java.base")
                             .reference("p6.indirect.UnsafeRef", "org.unsafe.UseUnsafe ", "unsafe")
@@ -121,7 +121,7 @@
 
     @Test(dataProvider = "modules")
     public void testModulePath(String name, List<ModuleMetaData> data) throws IOException {
-        Set<String> roots = Set.of("m6", "unsafe");
+        Set<String> roots = Set.of("mVI", "unsafe");
 
         String cmd1 = String.format("jdeps --module-path %s --add-modules %s -m %s%n", MODS_DIR,
             roots.stream().collect(Collectors.joining(",")), name);
@@ -152,13 +152,13 @@
     @DataProvider(name = "jars")
     public Object[][] expected2() {
         return new Object[][]{
-            { "m7", List.of(new ModuleMetaData("m7.jar")
-                                .requires("m6.jar")
+            { "mVII", List.of(new ModuleMetaData("mVII.jar")
+                                .requires("mVI.jar")
                                 .requires("unsafe.jar")
                                 .reference("p7.Main", "java.lang.Object", "java.base")
                                 .reference("p7.Main", "java.lang.String", "java.base")
                                 .reference("p7.Main", "org.safe.Lib", "unsafe.jar")
-                                .reference("p7.Main", "p6.safe.Lib", "m6.jar"))
+                                .reference("p7.Main", "p6.safe.Lib", "mVI.jar"))
             },
         };
     }
@@ -185,15 +185,15 @@
     @DataProvider(name = "compileTimeView")
     public Object[][] expected3() {
         return new Object[][] {
-            {"m7",
-             List.of(new ModuleMetaData("m7.jar")
-                        .requires("m6.jar")
+            {"mVII",
+             List.of(new ModuleMetaData("mVII.jar")
+                        .requires("mVI.jar")
                         .requires("unsafe.jar")
                         .reference("p7.Main", "java.lang.Object", "java.base")
                         .reference("p7.Main", "java.lang.String", "java.base")
                         .reference("p7.Main", "org.safe.Lib", "unsafe.jar")
-                        .reference("p7.Main", "p6.safe.Lib", "m6.jar"),
-                    new ModuleMetaData("m6.jar")
+                        .reference("p7.Main", "p6.safe.Lib", "mVI.jar"),
+                    new ModuleMetaData("mVI.jar")
                         .requires("unsafe.jar")
                         .reference("p6.indirect.UnsafeRef", "java.lang.Object", "java.base")
                         .reference("p6.indirect.UnsafeRef", "org.unsafe.UseUnsafe ", "unsafe.jar")
@@ -240,15 +240,15 @@
     @DataProvider(name = "recursiveDeps")
     public Object[][] expected4() {
         return new Object[][] {
-            {"m7",
-                List.of(new ModuleMetaData("m7.jar")
-                        .requires("m6.jar")
+            {"mVII",
+                List.of(new ModuleMetaData("mVII.jar")
+                        .requires("mVI.jar")
                         .requires("unsafe.jar")
                         .reference("p7.Main", "java.lang.Object", "java.base")
                         .reference("p7.Main", "java.lang.String", "java.base")
                         .reference("p7.Main", "org.safe.Lib", "unsafe.jar")
-                        .reference("p7.Main", "p6.safe.Lib", "m6.jar"),
-                    new ModuleMetaData("m6.jar")
+                        .reference("p7.Main", "p6.safe.Lib", "mVI.jar"),
+                    new ModuleMetaData("mVI.jar")
                         .requires("unsafe.jar")
                         .reference("p6.safe.Lib", "java.io.PrintStream", "java.base")
                         .reference("p6.safe.Lib", "java.lang.Class", "java.base")
diff --git a/langtools/test/tools/jdeps/modules/src/m4/module-info.java b/langtools/test/tools/jdeps/modules/src/m4/module-info.java
index d494909..38288bf 100644
--- a/langtools/test/tools/jdeps/modules/src/m4/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/m4/module-info.java
@@ -23,7 +23,7 @@
 
 module m4 {
     // not used in signature
-    requires public java.compiler;
+    requires transitive java.compiler;
 
     // unused dependence
     requires java.logging;
@@ -31,5 +31,5 @@
     exports p4;
 
     // unuused qualified exports
-    exports p4.internal to m6,m7;
+    exports p4.internal to mVI,mVII;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m5/module-info.java b/langtools/test/tools/jdeps/modules/src/m5/module-info.java
index ccdfccd..f8d05e4 100644
--- a/langtools/test/tools/jdeps/modules/src/m5/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/m5/module-info.java
@@ -22,15 +22,15 @@
  */
 
 module m5 {
-    // m4 requires public java.compiler
-    requires public m4;
-    requires public java.compiler;
+    // m4 requires transitive java.compiler
+    requires transitive m4;
+    requires transitive java.compiler;
 
-    // java.sql should be requires public
+    // java.sql should be requires transitive
     requires java.sql;
 
     // java.logging is used for implementation only
-    requires public java.logging;
+    requires transitive java.logging;
 
     exports p5;
 
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/jdeps/modules/src/mI/module-info.java
similarity index 98%
rename from langtools/test/tools/jdeps/modules/src/m1/module-info.java
rename to langtools/test/tools/jdeps/modules/src/mI/module-info.java
index 9d2c8be..46e4d6b 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/mI/module-info.java
@@ -21,7 +21,7 @@
  * questions.
  */
 
-module m1 {
+module mI {
     requires unsupported;
     exports p1;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/Goo.java b/langtools/test/tools/jdeps/modules/src/mI/p1/Goo.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m1/p1/Goo.java
rename to langtools/test/tools/jdeps/modules/src/mI/p1/Goo.java
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/Lib.java b/langtools/test/tools/jdeps/modules/src/mI/p1/Lib.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m1/p1/Lib.java
rename to langtools/test/tools/jdeps/modules/src/mI/p1/Lib.java
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/S.java b/langtools/test/tools/jdeps/modules/src/mI/p1/S.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m1/p1/S.java
rename to langtools/test/tools/jdeps/modules/src/mI/p1/S.java
diff --git a/langtools/test/tools/jdeps/modules/src/m1/p1/internal/Impl.java b/langtools/test/tools/jdeps/modules/src/mI/p1/internal/Impl.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m1/p1/internal/Impl.java
rename to langtools/test/tools/jdeps/modules/src/mI/p1/internal/Impl.java
diff --git a/langtools/test/tools/jdeps/modules/src/m2/module-info.java b/langtools/test/tools/jdeps/modules/src/mII/module-info.java
similarity index 93%
rename from langtools/test/tools/jdeps/modules/src/m2/module-info.java
rename to langtools/test/tools/jdeps/modules/src/mII/module-info.java
index 8a5d623..511cee4 100644
--- a/langtools/test/tools/jdeps/modules/src/m2/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/mII/module-info.java
@@ -21,8 +21,8 @@
  * questions.
  */
 
-module m2 {
-    requires public m1;
+module mII {
+    requires transitive mI;
     exports p2;
-    exports p2.internal to m3;
+    exports p2.internal to mIII;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m2/p2/Bar.java b/langtools/test/tools/jdeps/modules/src/mII/p2/Bar.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m2/p2/Bar.java
rename to langtools/test/tools/jdeps/modules/src/mII/p2/Bar.java
diff --git a/langtools/test/tools/jdeps/modules/src/m2/p2/internal/T2.java b/langtools/test/tools/jdeps/modules/src/mII/p2/internal/T2.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m2/p2/internal/T2.java
rename to langtools/test/tools/jdeps/modules/src/mII/p2/internal/T2.java
diff --git a/langtools/test/tools/jdeps/modules/src/m3/module-info.java b/langtools/test/tools/jdeps/modules/src/mIII/module-info.java
similarity index 91%
rename from langtools/test/tools/jdeps/modules/src/m3/module-info.java
rename to langtools/test/tools/jdeps/modules/src/mIII/module-info.java
index 62557e8..4677ed5 100644
--- a/langtools/test/tools/jdeps/modules/src/m3/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/mIII/module-info.java
@@ -21,10 +21,10 @@
  * questions.
  */
 
-module m3 {
-    requires public java.sql;
-    requires public m2;
+module mIII {
+    requires transitive java.sql;
+    requires transitive mII;
     requires java.logging;   // TODO: --generate-module-info to do transitive reduction
-    requires public m1;
+    requires transitive mI;
     exports p3;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m3/p3/Foo.java b/langtools/test/tools/jdeps/modules/src/mIII/p3/Foo.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m3/p3/Foo.java
rename to langtools/test/tools/jdeps/modules/src/mIII/p3/Foo.java
diff --git a/langtools/test/tools/jdeps/modules/src/m3/p3/Main.java b/langtools/test/tools/jdeps/modules/src/mIII/p3/Main.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m3/p3/Main.java
rename to langtools/test/tools/jdeps/modules/src/mIII/p3/Main.java
diff --git a/langtools/test/tools/jdeps/modules/src/m6/module-info.java b/langtools/test/tools/jdeps/modules/src/mVI/module-info.java
similarity index 98%
rename from langtools/test/tools/jdeps/modules/src/m6/module-info.java
rename to langtools/test/tools/jdeps/modules/src/mVI/module-info.java
index 374fbfa..40ea762 100644
--- a/langtools/test/tools/jdeps/modules/src/m6/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/mVI/module-info.java
@@ -21,7 +21,7 @@
  * questions.
  */
 
-module m6 {
+module mVI {
     requires unsafe;
 
     // no dependency on sun.misc.Unsafe directly or indirectly
diff --git a/langtools/test/tools/jdeps/modules/src/m6/p6/indirect/UnsafeRef.java b/langtools/test/tools/jdeps/modules/src/mVI/p6/indirect/UnsafeRef.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m6/p6/indirect/UnsafeRef.java
rename to langtools/test/tools/jdeps/modules/src/mVI/p6/indirect/UnsafeRef.java
diff --git a/langtools/test/tools/jdeps/modules/src/m6/p6/safe/Lib.java b/langtools/test/tools/jdeps/modules/src/mVI/p6/safe/Lib.java
similarity index 100%
rename from langtools/test/tools/jdeps/modules/src/m6/p6/safe/Lib.java
rename to langtools/test/tools/jdeps/modules/src/mVI/p6/safe/Lib.java
diff --git a/langtools/test/tools/jdeps/modules/src/m7/module-info.java b/langtools/test/tools/jdeps/modules/src/mVII/module-info.java
similarity index 97%
rename from langtools/test/tools/jdeps/modules/src/m7/module-info.java
rename to langtools/test/tools/jdeps/modules/src/mVII/module-info.java
index 408efc2..5a7dc37 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/mVII/module-info.java
@@ -21,9 +21,9 @@
  * questions.
  */
 
-module m7 {
+module mVII {
     // only use classes that have no direct or indirect dependency
     // to sun.misc.Unsafe
     requires unsafe;
-    requires m6;
+    requires mVI;
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/langtools/test/tools/jdeps/modules/src/mVII/p7/Main.java
similarity index 95%
rename from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
rename to langtools/test/tools/jdeps/modules/src/mVII/p7/Main.java
index 789cdb9..5f48b04 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/langtools/test/tools/jdeps/modules/src/mVII/p7/Main.java
@@ -23,7 +23,7 @@
 
 package p7;
 
-// Only use classes in unsafe and m6 modules with no
+// Only use classes in unsafe and mVI modules with no
 // direct or indirect dependency on sun.misc.Unsafe
 public class Main {
     public static void main(String... args) {
diff --git a/langtools/test/tools/jdeps/modules/src/provider/META-INF/services/java.util.spi.ToolProvider b/langtools/test/tools/jdeps/modules/src/provider/META-INF/services/java.util.spi.ToolProvider
new file mode 100644
index 0000000..b102354
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/provider/META-INF/services/java.util.spi.ToolProvider
@@ -0,0 +1,3 @@
+q.ProviderImpl3
+q.ProviderImpl2
+q.ProviderImpl1
diff --git a/langtools/test/tools/jdeps/modules/src/provider/META-INF/services/p.Service$I$J b/langtools/test/tools/jdeps/modules/src/provider/META-INF/services/p.Service$I$J
new file mode 100644
index 0000000..eb6238c
--- /dev/null
+++ b/langtools/test/tools/jdeps/modules/src/provider/META-INF/services/p.Service$I$J
@@ -0,0 +1 @@
+p.Provider$Impl
diff --git a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java b/langtools/test/tools/jdeps/modules/src/provider/module-info.java
similarity index 81%
copy from langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
copy to langtools/test/tools/jdeps/modules/src/provider/module-info.java
index 242f168..27e4922 100644
--- a/langtools/test/tools/javac/diags/examples/LeaksNotAccessibleNotRequiredPublic/LeaksNotAccessibleNotRequiredPublic.java
+++ b/langtools/test/tools/jdeps/modules/src/provider/module-info.java
@@ -21,5 +21,14 @@
  * questions.
  */
 
-// key: compiler.warn.leaks.not.accessible.not.required.public
-// options: -Xlint:exports
+module provider {
+    provides java.util.spi.ToolProvider with
+        q.ProviderImpl3,
+        q.ProviderImpl2,
+        q.ProviderImpl1;
+
+    uses p.Service.I.J;
+
+    // nested types
+    provides p.Service.I.J with p.Provider.Impl;
+}
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/jdeps/modules/src/provider/p/Provider.java
similarity index 91%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/jdeps/modules/src/provider/p/Provider.java
index 9d2c8be..cb1fa26 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/provider/p/Provider.java
@@ -21,7 +21,9 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+package p;
+
+public class Provider {
+    public static class Impl implements Service.I.J {
+    }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m1/module-info.java b/langtools/test/tools/jdeps/modules/src/provider/p/Service.java
similarity index 90%
copy from langtools/test/tools/jdeps/modules/src/m1/module-info.java
copy to langtools/test/tools/jdeps/modules/src/provider/p/Service.java
index 9d2c8be..4164c48 100644
--- a/langtools/test/tools/jdeps/modules/src/m1/module-info.java
+++ b/langtools/test/tools/jdeps/modules/src/provider/p/Service.java
@@ -21,7 +21,11 @@
  * questions.
  */
 
-module m1 {
-    requires unsupported;
-    exports p1;
+package p;
+
+public class Service {
+    public static class I {
+        public static interface J {}
+    }
 }
+
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl1.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl1.java
index 789cdb9..f68eb7a 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl1.java
@@ -21,13 +21,17 @@
  * questions.
  */
 
-package p7;
+package q;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.io.*;
+import java.util.spi.ToolProvider;
+
+public class ProviderImpl1 implements ToolProvider {
+    public String name() {
+        return "provider1";
+    }
+
+    public int run(PrintWriter out, PrintWriter err, String... args) {
+        return 0;
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl2.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl2.java
index 789cdb9..72a3dbb 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl2.java
@@ -21,13 +21,17 @@
  * questions.
  */
 
-package p7;
+package q;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.io.*;
+import java.util.spi.ToolProvider;
+
+public class ProviderImpl2 implements ToolProvider {
+    public String name() {
+        return "provider2";
+    }
+
+    public int run(PrintWriter out, PrintWriter err, String... args) {
+        return 0;
     }
 }
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl3.java
similarity index 79%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl3.java
index 789cdb9..d6f456c 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/langtools/test/tools/jdeps/modules/src/provider/q/ProviderImpl3.java
@@ -21,13 +21,17 @@
  * questions.
  */
 
-package p7;
+package q;
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
+import java.io.*;
+import java.util.spi.ToolProvider;
+
+public class ProviderImpl3 implements ToolProvider {
+    public String name() {
+        return "provider3";
+    }
+
+    public int run(PrintWriter out, PrintWriter err, String... args) {
+        return 0;
     }
 }
diff --git a/langtools/test/tools/lib/toolbox/ModuleBuilder.java b/langtools/test/tools/lib/toolbox/ModuleBuilder.java
index 8c73902..f1ece37 100644
--- a/langtools/test/tools/lib/toolbox/ModuleBuilder.java
+++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.java
@@ -72,51 +72,132 @@
     }
 
     /**
-     * Adds a "requires public" directive to the declaration.
-     * @param requires the name of the module that is required
+     * Adds a "requires" directive to the declaration.
+     * @param module the name of the module that is required
+     * @param modulePath a path in while to locate the modules
+     *    if the declaration is compiled
+     * @return this builder
+     */
+    public ModuleBuilder requires(String module, Path... modulePath) {
+        addDirective(requires, "requires " + module + ";");
+        this.modulePath.addAll(Arrays.asList(modulePath));
+        return this;
+
+    }
+
+    /**
+     * Adds a "requires static" directive to the declaration.
+     * @param module the name of the module that is required
      * @param modulePath a path in which to locate the modules
      *    if the declaration is compiled
      * @return this builder
      */
-    public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
-        this.requires.add("requires public " + requires + ";");
+    public ModuleBuilder requiresStatic(String module, Path... modulePath) {
+        addDirective(requires, "requires static " + module + ";");
         this.modulePath.addAll(Arrays.asList(modulePath));
         return this;
     }
 
     /**
-     * Adds a "requires" directive to the declaration.
-     * @param requires the name of the module that is required
-     * @param modulePath a path in while to locate the modules
+     * Adds a "requires transitive" directive to the declaration.
+     * @param module the name of the module that is required
+     * @param modulePath a path in which to locate the modules
      *    if the declaration is compiled
      * @return this builder
      */
-    public ModuleBuilder requires(String requires, Path... modulePath) {
-        this.requires.add("requires " + requires + ";");
+    public ModuleBuilder requiresTransitive(String module, Path... modulePath) {
+        addDirective(requires, "requires transitive " + module + ";");
         this.modulePath.addAll(Arrays.asList(modulePath));
         return this;
     }
 
     /**
+     * Adds a "requires static transitive" directive to the declaration.
+     * @param module the name of the module that is required
+     * @param modulePath a path in which to locate the modules
+     *    if the declaration is compiled
+     * @return this builder
+     */
+    public ModuleBuilder requiresStaticTransitive(String module, Path... modulePath) {
+        addDirective(requires, "requires static transitive " + module + ";");
+        this.modulePath.addAll(Arrays.asList(modulePath));
+        return this;
+    }
+
+    /**
+     * Adds an unqualified "exports" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @return this builder
+     */
+    public ModuleBuilder exports(String pkg) {
+        return addDirective(exports, "exports " + pkg + ";");
+    }
+
+    /**
+     * Adds an unqualified "exports dynamic" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @return this builder
+     */
+    public ModuleBuilder exportsDynamic(String pkg) {
+        return addDirective(exports, "exports dynamic " + pkg + ";");
+    }
+
+    /**
+     * Adds an unqualified "exports private" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @return this builder
+     */
+    public ModuleBuilder exportsPrivate(String pkg) {
+        return addDirective(exports, "exports private " + pkg + ";");
+    }
+
+    /**
+     * Adds an unqualified "exports dynamic private" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @return this builder
+     */
+    public ModuleBuilder exportsDynamicPrivate(String pkg) {
+        return addDirective(exports, "exports dynamic private " + pkg + ";");
+    }
+
+    /**
      * Adds a qualified "exports" directive to the declaration.
      * @param pkg the name of the package to be exported
      * @param module the name of the module to which it is to be exported
      * @return this builder
      */
     public ModuleBuilder exportsTo(String pkg, String module) {
-        this.exports.add("exports " + pkg + " to " + module + ";");
-        return this;
+        return addDirective(exports, "exports " + pkg + " to " + module + ";");
     }
 
     /**
-     * Adds an unqualified "exports" directive to the declaration.
+     * Adds a qualified "exports dynamic" directive to the declaration.
      * @param pkg the name of the package to be exported
      * @param module the name of the module to which it is to be exported
      * @return this builder
      */
-    public ModuleBuilder exports(String pkg) {
-        this.exports.add("exports " + pkg + ";");
-        return this;
+    public ModuleBuilder exportsDynamicTo(String pkg, String module) {
+        return addDirective(exports, "exports dynamic " + pkg + " to " + module + ";");
+    }
+
+    /**
+     * Adds a qualified "exports private" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @param module the name of the module to which it is to be exported
+     * @return this builder
+     */
+    public ModuleBuilder exportsPrivateTo(String pkg, String module) {
+        return addDirective(exports, "exports private " + pkg + " to " + module + ";");
+    }
+
+    /**
+     * Adds a qualified "exports dynamic private" directive to the declaration.
+     * @param pkg the name of the package to be exported
+     * @param module the name of the module to which it is to be exported
+     * @return this builder
+     */
+    public ModuleBuilder exportsDynamicPrivateTo(String pkg, String module) {
+        return addDirective(exports, "exports dynamic private " + pkg + " to " + module + ";");
     }
 
     /**
@@ -125,8 +206,7 @@
      * @return this builder
      */
     public ModuleBuilder uses(String service) {
-        this.uses.add("uses " + service + ";");
-        return this;
+        return addDirective(uses, "uses " + service + ";");
     }
 
     /**
@@ -136,7 +216,11 @@
      * @return this builder
      */
     public ModuleBuilder provides(String service, String implementation) {
-        this.provides.add("provides " + service + " with " + implementation + ";");
+        return addDirective(provides, "provides " + service + " with " + implementation + ";");
+    }
+
+    private ModuleBuilder addDirective(List<String> directives, String directive) {
+        directives.add(directive);
         return this;
     }
 
diff --git a/langtools/test/tools/sjavac/Serialization.java b/langtools/test/tools/sjavac/Serialization.java
index 58d0cef..8d6e524 100644
--- a/langtools/test/tools/sjavac/Serialization.java
+++ b/langtools/test/tools/sjavac/Serialization.java
@@ -61,7 +61,7 @@
                 Option.SRC.arg, "root",
                 Option.SOURCEPATH.arg, "sourcepath",
                 Option.CLASSPATH.arg, "classpath",
-                Option.MODULEPATH.arg, "modulepath",
+                Option.MODULE_PATH.arg, "modulepath",
                 Option.PERMIT_SOURCES_WITHOUT_PACKAGE.arg,
                 Option.PERMIT_UNIDENTIFIED_ARTIFACTS.arg,
                 Option.TR.arg, ".prop=" + CompileJavaPackages.class.getName(),
diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk
index c222a40..59d317a 100644
--- a/make/CompileJavaModules.gmk
+++ b/make/CompileJavaModules.gmk
@@ -356,10 +356,6 @@
 
 ################################################################################
 
-jdk.jshell_ADD_JAVAC_FLAGS := -Xlint:-exports
-
-################################################################################
-
 jdk.hotspot.agent_ADD_JAVAC_FLAGS := $(DISABLE_WARNINGS),-overrides
 jdk.hotspot.agent_COPY := .gif .png sa.js .properties
 
diff --git a/make/CreateHgtipFiles.gmk b/make/CreateHgtipFiles.gmk
deleted file mode 100644
index 61e7be1..0000000
--- a/make/CreateHgtipFiles.gmk
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-default: all
-
-include $(SPEC)
-include MakeBase.gmk
-
-define SetupCreateHgtip
-
-  $$(strip $1)/$(HGTIP_FILENAME): FRC
-	$(HG) tip --repository $$(strip $1) --template '{node|short}\n' > $$@.tmp
-	if [ ! -f $$@ ] || [ "`$(CAT) $$@`" != "`$(CAT) $$@.tmp`" ]; then \
-	  $(MV) $$@.tmp $$@ ; \
-	else \
-	  $(RM) $$@.tmp ; \
-	fi
-
-  TARGETS += $$(strip $1)/$(HGTIP_FILENAME)
-
-endef
-
-# Only try to create the tips if finding an actual hg repository. This will be
-# false if building from a source bundle.
-$(foreach r, $(call FindAllReposAbs), \
-  $(if $(wildcard $r/.hg), $(eval $(call SetupCreateHgtip, $r))) \
-)
-
-all: $(TARGETS)
-
-FRC:
-
-.PHONY: all
diff --git a/make/GensrcModuleInfo.gmk b/make/GensrcModuleInfo.gmk
index cd0c3af..25ade7f 100644
--- a/make/GensrcModuleInfo.gmk
+++ b/make/GensrcModuleInfo.gmk
@@ -60,8 +60,8 @@
 
 ################################################################################
 
-# Name of data file. Keep module-info.java.ext until javafx has changed.
-MOD_FILENAME := module-info.java.extra module-info.java.ext
+# Name of modification file.
+MOD_FILENAME := module-info.java.extra
 
 # Construct all possible src directories for the module.
 MODULE_CLASSES_DIRS := $(call FindModuleSrcDirs, $(MODULE))
@@ -74,74 +74,24 @@
   # Only make this call if modification files are found for this module
   ALL_MODULES := $(call FindAllModules)
 
-  # Read the contents of all the files into a variable. Replace space with / to
-  # let space represent new lines in the variable as $(shell) normalizes all
-  # whitespace.
-  $(foreach f, $(MOD_FILES), \
-    $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v -e ".\*" -e "//" $f | $(TR) ' ' '/')))
-
-  # Separate the modifications into qualified exports and the rest
-  MODS_QUALIFIED_EXPORTS := $(call containing, /to/, $(MOD_FILE_CONTENTS))
-  MODS_REST := $(filter-out $(MODS_QUALIFIED_EXPORTS), $(MOD_FILE_CONTENTS))
-
-  # Filter the contents for modules that are actually being built
-  ALL_MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES)))
-  MODIFICATIONS := $(filter $(ALL_MODULES_FILTER), $(MODS_QUALIFIED_EXPORTS)) \
-      $(MODS_REST)
-
-  # Returns non empty if the package exists in the current module
-  # Param 1 - Name of package with dots
-  PackageExists = \
-      $(strip $(wildcard $(addsuffix $(subst .,/,/$(strip $1)), \
-          $(MODULE_CLASSES_DIRS) \
-          $(addsuffix /$(MODULE), $(IMPORT_MODULES_CLASSES)) \
-          $(JDK_OUTPUTDIR)/modules/$(MODULE) \
-      )))
-
-  # Convert the modification lines into arguments for the modification tool.
-  # Filter out modifications for non existing to-modules.
-  $(foreach line, $(MODIFICATIONS), \
-    $(eval split_line := $(subst /,$(SPACE),$(line))) \
-    $(eval command := $(word 1, $(split_line))) \
-    $(if $(filter $(command), exports), \
-      $(eval package := $(patsubst %;,%,$(word 2, $(split_line)))) \
-      $(if $(call PackageExists, $(package)), \
-        $(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \
-        $(if $(to_module), \
-          $(eval ARGS += -$(command) $(package)/$(to_module)) \
-        , \
-          $(eval ARGS += -$(command) $(package)) \
-        ) \
-      ) \
-    , \
-      $(if $(filter $(command), provides), \
-        $(eval provider := $(patsubst %;,%,$(word 2, $(split_line)))) \
-        $(eval class := $(patsubst %;,%,$(word 4, $(split_line)))) \
-        $(eval ARGS += -$(command) $(provider)/$(class)) \
-      , \
-        $(error A module-info.extra in $(MODULE) contains invalid command $(command)) \
-      ) \
-    ) \
-  )
-
-  ifneq ($(ARGS), )
-    $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \
-        $(firstword $(call FindAllModuleInfos, $(MODULE))) \
-        $(BUILD_TOOLS_JDK) \
-        $(call DependOnVariable, ARGS)
+  $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \
+      $(firstword $(call FindAllModuleInfos, $(MODULE))) \
+      $(BUILD_TOOLS_JDK) \
+      $(MOD_FILES) \
+      $(call DependOnVariable, ALL_MODULES)
 		$(MKDIR) -p $(@D)
 		$(RM) $@ $@.tmp
-		$(TOOL_GENMODULEINFOSOURCE) $(ARGS) -o $@.tmp $<
+		$(TOOL_GENMODULEINFOSOURCE) -o $@.tmp \
+		    --source-file $< \
+		    --modules $(call CommaList, $(ALL_MODULES)) \
+		    $(MOD_FILES)
 		$(MV) $@.tmp $@
 
-    TARGETS += $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java
-  endif
+  TARGETS += $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java
 
-endif
-
-# If no modifications are found for this module, remove any module-info.java
-# created by a previous build since that is no longer valid.
-ifeq ($(MODIFICATIONS), )
+else
+  # If no modifications are found for this module, remove any module-info.java
+  # created by a previous build since that is no longer valid.
   ifneq ($(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java), )
     $(shell $(RM) $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java)
   endif
diff --git a/make/Images.gmk b/make/Images.gmk
index f9bc0e2..fa3d3ba 100644
--- a/make/Images.gmk
+++ b/make/Images.gmk
@@ -48,7 +48,8 @@
 JDK_MODULES += $(ALL_MODULES)
 
 # Compact builds have additional modules
-COMPACT1_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec
+COMPACT1_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec \
+    jdk.unsupported
 COMPACT2_EXTRA_MODULES := jdk.xml.dom jdk.httpserver
 COMPACT3_EXTRA_MODULES := java.smartcardio jdk.management \
     jdk.naming.dns jdk.naming.rmi jdk.sctp jdk.security.auth
@@ -64,47 +65,9 @@
 JRE_COMPACT3_MODULES_LIST := $(call CommaList, $(JRE_COMPACT3_MODULES))
 
 ################################################################################
-# Release file
 
 BASE_RELEASE_FILE := $(JDK_OUTPUTDIR)/release
 
-# Common way to emit a line into the release or info file
-define info-file-item # name value
-  $(PRINTF) '%s="%s"\n' $1 $2 >> $@
-endef
-
-# Param 1 - The file containing the MODULES list
-define create-info-file
-  $(if $(JDK_ARCH_ABI_PROP_NAME), \
-    $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
-  $(call info-file-item, "SOURCE", "$(strip $(ALL_SOURCE_TIPS))")
-endef
-
-# Param 1 - The file containing the MODULES list
-define prepare-info-file
-  $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
-  $(MKDIR) -p $(@D)
-  $(RM) $@
-endef
-
-define info-file
-  $(call prepare-info-file)
-  $(call create-info-file)
-endef
-
-# Create a variable dependency file common for all release info files.
-INFO_FILE_VARDEPS := $(call DependOnVariable, create-info-file)
-
-ALL_SOURCE_TIPS = $(shell \
-    if [ -f $(SUPPORT_OUTPUTDIR)/source_tips ] ; then \
-      $(CAT) $(SUPPORT_OUTPUTDIR)/source_tips ; \
-    fi)
-
-$(BASE_RELEASE_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
-	$(info-file)
-
-################################################################################
-
 JMODS := $(wildcard $(IMAGES_OUTPUTDIR)/jmods/*.jmod)
 
 # Use this file inside the image as target for make rule
@@ -124,7 +87,8 @@
     /jdk.localedata/** \
     #
 
-JLINK_TOOL := $(JLINK) --module-path $(IMAGES_OUTPUTDIR)/jmods \
+JLINK_TOOL := $(JLINK) -J-Djlink.debug=true \
+    --module-path $(IMAGES_OUTPUTDIR)/jmods \
     --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
     --release-info $(BASE_RELEASE_FILE) \
     --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \
@@ -400,16 +364,6 @@
 JDK_TARGETS += $(COPY_SAMPLES)
 
 ################################################################################
-# jrt-fs.jar
-
-$(eval $(call SetupCopyFiles,COPY_JRTFS_JAR, \
-    SRC := $(SUPPORT_OUTPUTDIR), \
-    DEST := $(JDK_IMAGE_DIR), \
-    FILES := $(SUPPORT_OUTPUTDIR)/jrt-fs.jar))
-
-JDK_TARGETS += $(COPY_JRTFS_JAR)
-
-################################################################################
 # Code coverage data files
 
 ifeq ($(GCOV_ENABLED), true)
diff --git a/make/Init.gmk b/make/Init.gmk
index 2e391a4..15d25b4 100644
--- a/make/Init.gmk
+++ b/make/Init.gmk
@@ -157,7 +157,7 @@
     # Do not let make delete spec files even if aborted while doing a reconfigure
     .PRECIOUS: $(SPECS)
 
-    # Unless reconfigure is explicitely called, let all main targets depend on
+    # Unless reconfigure is explicitly called, let all main targets depend on
     # the spec files to be up to date.
     ifeq ($(findstring reconfigure, $(INIT_TARGETS)), )
       $(MAIN_TARGETS): $(SPECS)
@@ -278,7 +278,7 @@
 
   # MAKEOVERRIDES is automatically set and propagated by Make to sub-Make calls.
   # We need to clear it of the init-specific variables. The user-specified
-  # variables are explicitely propagated using $(USER_MAKE_VARS).
+  # variables are explicitly propagated using $(USER_MAKE_VARS).
   main: MAKEOVERRIDES :=
 
   main: $(INIT_TARGETS)
diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk
index b8c4da3..b0c9a7e 100644
--- a/make/Javadoc.gmk
+++ b/make/Javadoc.gmk
@@ -33,7 +33,7 @@
 # Allow custom to overwrite.
 JAVADOC_SOURCE_DIRS = \
       $(SUPPORT_OUTPUTDIR)/gensrc/* \
-      $(if $(IMPORT_MODULES_SRC), $(IMPORT_MODULES_SRC)/*) \
+      $(addsuffix /*, $(IMPORT_MODULES_SRC)) \
       $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS)/classes \
       $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS_TYPE)/classes \
       $(JDK_TOPDIR)/src/*/share/classes \
diff --git a/make/JrtfsJar.gmk b/make/JrtfsJar.gmk
index 36ba0be..a950490 100644
--- a/make/JrtfsJar.gmk
+++ b/make/JrtfsJar.gmk
@@ -65,7 +65,7 @@
 $(eval $(call SetupJarArchive,BUILD_JRTFS_JAR, \
     DEPENDENCIES := $(BUILD_JRTFS) $(COPY_JIMAGE_SERVICE_PROVIDER), \
     SRCS := $(SUPPORT_OUTPUTDIR)/jrtfs_classes, \
-    JAR := $(SUPPORT_OUTPUTDIR)/jrt-fs.jar, \
+    JAR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jrt-fs.jar, \
     MANIFEST := $(SUPPORT_OUTPUTDIR)/java-main-manifest.mf, \
 ))
 
diff --git a/make/Main.gmk b/make/Main.gmk
index 60c705d..e264d91 100644
--- a/make/Main.gmk
+++ b/make/Main.gmk
@@ -284,16 +284,11 @@
 ################################################################################
 # Images targets
 
-# Stores the tips for each repository. This file is be used when constructing
-# the jdk image and can be used to track the exact sources used to build that
-# image.
-source-tips: $(SUPPORT_OUTPUTDIR)/source_tips
-$(SUPPORT_OUTPUTDIR)/source_tips: FRC
-	$(call MakeDir, $(@D))
-	$(call GetSourceTips)
+store-source-revision:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f SourceRevision.gmk store-source-revision)
 
-create-hgtip-files:
-	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CreateHgtipFiles.gmk)
+create-source-revision-tracker:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f SourceRevision.gmk create-source-revision-tracker)
 
 BOOTCYCLE_TARGET := product-images
 bootcycle-images:
@@ -329,13 +324,16 @@
 mac-bundles-jdk:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f MacBundles.gmk)
 
+release-file:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f ReleaseFile.gmk)
+
 exploded-image-optimize:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f ExplodedImageOptimize.gmk)
 
-ALL_TARGETS += source-tips create-hgtip-files bootcycle-images zip-security \
+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 \
-    exploded-image-optimize
+    release-file exploded-image-optimize
 
 ################################################################################
 # Docs targets
@@ -608,12 +606,12 @@
 
   jdk.jdeps-gendata: java rmic
 
-  # Declare dependencies between jmod targets. Only java.base jmod needs access
-  # to the other jmods to be built.
+  # Declare dependencies between jmod targets.
+  # java.base jmod needs jrt-fs.jar and access to the other jmods to be built.
   # When creating a BUILDJDK, we don't need to add hashes to java.base, thus
   # we don't need to depend on all other jmods
   ifneq ($(CREATING_BUILDJDK), true)
-    java.base-jmod: $(filter-out java.base-jmod \
+    java.base-jmod: jrtfs-jar $(filter-out java.base-jmod \
         $(addsuffix -jmod, $(call FindAllUpgradeableModules)), $(JMOD_TARGETS))
   endif
 
@@ -684,10 +682,12 @@
     java.base-jmod jdk-image jre-image: generate-link-opt-data
   endif
 
-  jdk-image: jmods zip-source source-tips demos samples jrtfs-jar
-  jre-image: jmods source-tips jrtfs-jar
+  release-file: create-source-revision-tracker
 
-  profiles: jmods zip-source source-tips jrtfs-jar
+  jdk-image: jmods zip-source demos samples release-file
+  jre-image: jmods release-file
+
+  profiles: jmods release-file
 
   mac-bundles-jdk: jdk-image jre-image
 
@@ -794,7 +794,7 @@
 
 # The "exploded image" is a locally runnable JDK in $(BUILD_OUTPUT)/jdk.
 exploded-image-base: $(ALL_MODULES)
-exploded-image: exploded-image-base
+exploded-image: exploded-image-base release-file
 # When cross compiling, no need to optimize the exploded image since it won't
 # be runnable on the host platform anyway.
 ifneq ($(COMPILE_TYPE), cross)
diff --git a/make/ReleaseFile.gmk b/make/ReleaseFile.gmk
new file mode 100644
index 0000000..d68d9e4
--- /dev/null
+++ b/make/ReleaseFile.gmk
@@ -0,0 +1,86 @@
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+################################################################################
+# This makefile generates the "release" file into the exploded image. Jlink is
+# then responsible for using this as the base for release files in each linked
+# image.
+#
+################################################################################
+
+BASE_RELEASE_FILE := $(JDK_OUTPUTDIR)/release
+
+# Common way to emit a line into the release or info file
+define info-file-item # name value
+  $(PRINTF) '%s="%s"\n' $1 $2 >> $@
+endef
+
+# Param 1 - The file containing the MODULES list
+define create-info-file
+  $(if $(JDK_ARCH_ABI_PROP_NAME), \
+    $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
+  $(call info-file-item, "SOURCE", "$(strip $(SOURCE_REVISION))")
+endef
+
+# Param 1 - The file containing the MODULES list
+define prepare-info-file
+  $(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@))
+  $(call MakeDir, $(@D))
+  $(RM) $@
+endef
+
+define info-file
+  $(call prepare-info-file)
+  $(call create-info-file)
+endef
+
+# Create a variable dependency file common for all release info files.
+INFO_FILE_VARDEPS := $(call DependOnVariable, create-info-file)
+
+SOURCE_REVISION = $(shell \
+    if [ -f $(SOURCE_REVISION_TRACKER) ] ; then \
+      $(CAT) $(SOURCE_REVISION_TRACKER) ; \
+    fi)
+
+# The SOURCE_REVISION_TRACKER file may not exist. Only depend on it if it does.
+$(BASE_RELEASE_FILE): $(INFO_FILE_VARDEPS) $(wildcard $(SOURCE_REVISION_TRACKER))
+	$(info-file)
+
+TARGETS += $(BASE_RELEASE_FILE)
+
+################################################################################
+
+$(eval $(call IncludeCustomExtension, , ReleaseFile.gmk))
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: all default
diff --git a/make/SourceRevision.gmk b/make/SourceRevision.gmk
new file mode 100644
index 0000000..cdd77d7
--- /dev/null
+++ b/make/SourceRevision.gmk
@@ -0,0 +1,131 @@
+#
+# 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.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+################################################################################
+# Keep track of what source revision is used to create the build, by creating
+# a tracker file in the output directory. This tracker file is included in the
+# image, and can be used to recreate the source revision used.
+#
+# We're either building directly from a mercurial forest, and if so, use the
+# current revision from mercurial. Otherwise, we are building from a source
+# bundle. As a part of creating this source bundle, the current mercurial
+# revisions of all repos will be stored in a file in the top dir, which is then
+# used when creating the tracker file.
+
+STORED_SOURCE_REVISION := $(TOPDIR)/.src-rev
+
+# Are we using mercurial?
+ifneq ($(and $(HG), $(wildcard $(TOPDIR)/.hg)), )
+
+  # Verify that the entire forest is consistent
+  $(foreach repo, $(call FindAllReposRel), \
+    $(if $(wildcard $(TOPDIR)/$(repo)/.hg),, \
+        $(error Inconsistent revision control: $(repo) is missing .hg directory)) \
+  )
+
+  # Replace "." with "_top" and "/" with "-"
+  MakeFilenameFromRepo = \
+      $(strip $(subst .,top, $(subst /,-, $1)))
+
+  ################################################################################
+  # SetupGetRevisionForRepo defines a make rule for creating a file containing
+  # the name of the repository and the output of "hg id" for that repository.
+  # Argument 1 is the relative path to the repository from the top dir.
+  #
+  SetupGetRevisionForRepo = $(NamedParamsMacroTemplate)
+  define SetupGetRevisionForRepoBody
+    $1_REPO_PATH :=  $$(TOPDIR)/$$(strip $1)
+    $1_FILENAME := $$(call MakeFilenameFromRepo, $1)
+
+    $$(SUPPORT_OUTPUTDIR)/src-rev/$$($1_FILENAME): FRC
+	$$(call MakeDir, $$(@D))
+	$$(ECHO) $$(strip $1):`$$(HG) id -i --repository $$($1_REPO_PATH)` > $$@
+
+    REPO_REVISIONS += $$(SUPPORT_OUTPUTDIR)/src-rev/$$($1_FILENAME)
+  endef
+
+  # Setup rules for all repos. This makes sure all the "hg id" calls are made
+  # in parallel.
+  $(foreach repo, $(call FindAllReposRel), \
+    $(eval $(call SetupGetRevisionForRepo, $(repo))) \
+  )
+
+  # Create a complete source revision output file from all repos
+  # Param 1: The output file
+  define CreateSourceRevisionFile
+    $1: $$(REPO_REVISIONS)
+	$$(call MakeDir, $$(@D))
+	$$(ECHO) `$$(CAT) $$(REPO_REVISIONS)` > $$@.tmp
+	if [ ! -f $$@ ] || [ "`$$(CAT) $$@`" != "`$$(CAT) $$@.tmp`" ]; then \
+	  $$(MV) $$@.tmp $$@ ; \
+	else \
+	  $$(RM) $$@.tmp ; \
+	fi
+  endef
+
+  $(eval $(call CreateSourceRevisionFile, $(STORED_SOURCE_REVISION)))
+
+  store-source-revision: $(STORED_SOURCE_REVISION)
+
+  $(eval $(call CreateSourceRevisionFile, $(SOURCE_REVISION_TRACKER)))
+
+  create-source-revision-tracker: $(SOURCE_REVISION_TRACKER)
+
+else
+  # Not using HG
+
+  ifneq ($(wildcard $(STORED_SOURCE_REVISION)), )
+    # We have a stored source revision (.src-rev)
+
+    store-source-revision:
+	$(call LogWarn, Warning: No mercurial configuration present, not updating .src-rev)
+
+    $(SOURCE_REVISION_TRACKER): $(STORED_SOURCE_REVISION)
+	$(install-file)
+
+    create-source-revision-tracker: $(SOURCE_REVISION_TRACKER)
+  else
+    # We don't have a stored source revision. Can't do anything, really.
+
+    store-source-revision:
+	$(call LogWarn, Error: No mercurial configuration present, cannot create .src-rev)
+	exit 2
+
+    create-source-revision-tracker:
+	$(call LogWarn, Warning: No mercurial configuration present and no .src-rev)
+  endif
+
+endif
+
+all: store-source-revision create-source-revision-tracker
+
+FRC: # Force target
+
+.PHONY: all store-source-revision create-source-revision-tracker
diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk
index 9c2a3f1..c1e5022 100644
--- a/make/common/MakeBase.gmk
+++ b/make/common/MakeBase.gmk
@@ -337,44 +337,21 @@
 endif # HAS_FILE_FUNCTION
 
 ################################################################################
-# The source tips can come from the Mercurial repository, or in the files
-# $(HGTIP_FILENAME) which contains the tip but is also positioned in the same
-# directory as the original .hg directory. The hgtip files are created in
-# CreateHgtipFiles.gmk.
-HGTIP_FILENAME := .hgtip
+
+# A file containing a way to uniquely identify the source code revision that
+# the build was created from
+SOURCE_REVISION_TRACKER := $(SUPPORT_OUTPUTDIR)/src-rev/source-revision-tracker
+
+# Locate all hg repositories included in the forest, as absolute paths
 FindAllReposAbs = \
     $(strip $(sort $(dir $(filter-out $(SRC_ROOT)/build/%, $(wildcard \
-        $(addprefix $(SRC_ROOT)/, \
-            .hg */.hg */*/.hg */*/.hg */*/*/.hg \
-            .hgtip */.hgtip */*/.hgtip */*/.hgtip */*/*/.hgtip \
-        ) \
+        $(addprefix $(SRC_ROOT)/, .hg */.hg */*/.hg */*/*/.hg) \
     )))))
 
+# Locate all hg repositories included in the forest, as relative paths
 FindAllReposRel = \
     $(strip $(subst $(SRC_ROOT)/,.,$(patsubst $(SRC_ROOT)/%/, %, $(FindAllReposAbs))))
 
-# Emit the repo:tip pairs to $@, but only if they changed since last time
-define GetSourceTips
-	$(CD) $(SRC_ROOT) ; \
-	for i in $(FindAllReposRel) IGNORE ; do \
-	  if [ "$${i}" = "IGNORE" ] ; then \
-	    continue; \
-	  elif [ -d $${i}/.hg -a "$(HG)" != "" ] ; then \
-	    $(PRINTF) " %s:%s" \
-	        "$${i}" `$(HG) tip --repository $${i} --template '{node|short}\n'` ; \
-	  elif [ -f $${i}/$(HGTIP_FILENAME) ] ; then \
-	    $(PRINTF) " %s:%s" \
-	        "$${i}" `$(CAT) $${i}/$(HGTIP_FILENAME)` ; \
-	  fi; \
-	done > $@.tmp
-	$(PRINTF) "\n" >> $@.tmp
-	if [ ! -f $@ ] || [ "`$(CAT) $@`" != "`$(CAT) $@.tmp`" ]; then \
-	  $(MV) $@.tmp $@ ; \
-	else \
-	  $(RM) $@.tmp ; \
-	fi
-endef
-
 ################################################################################
 
 define SetupLogging
diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk
index bb1d059..eeb82b0f 100644
--- a/make/common/Modules.gmk
+++ b/make/common/Modules.gmk
@@ -171,12 +171,15 @@
 
 # Find all module-info.java files for the current build target platform and
 # configuration.
+# TODO: The $(firstword call is part of a workaround for using different
+# imported module-info.java in Jake due to a change in format. Remove once
+# new format is standard in JDK 9 and javafx delivers just that.
 # Param 1 - Module to find for, set to * for finding all
 FindAllModuleInfos = \
     $(wildcard \
         $(foreach sub, $(SRC_SUBDIRS), \
           $(patsubst %,%/$(strip $1)/$(sub)/module-info.java, $(TOP_SRC_DIRS))) \
-        $(patsubst %,%/$(strip $1)/module-info.java, $(IMPORT_MODULES_SRC)))
+        $(patsubst %,%/$(strip $1)/module-info.java, $(firstword $(IMPORT_MODULES_SRC))))
 
 # Find module-info.java files in the specific source dir
 # Param 1 - Src dir to find module-info.java files in
@@ -244,7 +247,7 @@
 	          BEGIN      { if (MODULE != "java.base") printf(" java.base"); } \
 	          /requires/ { sub(/;/, ""); \
 	                       sub(/requires/, ""); \
-	                       sub(/public/, ""); \
+	                       sub(/transitive/, ""); \
 	                       sub(/\/\/.*/, ""); \
 	                       sub(/\/\*.*\*\//, ""); \
 	                       gsub(/^ +\*.*/, ""); \
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index 36e0381..3a9cf47 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -568,17 +568,21 @@
   # Sort to remove dupliates and provide a reproducable order on the input files to the linker.
   $1_ALL_OBJS := $$(sort $$($1_EXPECTED_OBJS) $$($1_EXTRA_OBJECT_FILES))
 
-  # Pickup extra OPENJDK_TARGET_OS_TYPE and/or OPENJDK_TARGET_OS dependent variables for CFLAGS.
-  $1_EXTRA_CFLAGS:=$$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CFLAGS_$(OPENJDK_TARGET_OS))
+  # Pickup extra OPENJDK_TARGET_OS_TYPE, OPENJDK_TARGET_OS, and/or OPENJDK_TARGET_OS plus
+  # OPENJDK_TARGET_CPU pair dependent variables for CFLAGS.
+  $1_EXTRA_CFLAGS:=$$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CFLAGS_$(OPENJDK_TARGET_OS)) \
+      $$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU))
   ifneq ($(DEBUG_LEVEL),release)
     # Pickup extra debug dependent variables for CFLAGS
     $1_EXTRA_CFLAGS+=$$($1_CFLAGS_debug)
     $1_EXTRA_CFLAGS+=$$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_debug)
     $1_EXTRA_CFLAGS+=$$($1_CFLAGS_$(OPENJDK_TARGET_OS)_debug)
+    $1_EXTRA_CFLAGS+=$$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_debug)
   else
     $1_EXTRA_CFLAGS+=$$($1_CFLAGS_release)
     $1_EXTRA_CFLAGS+=$$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)_release)
     $1_EXTRA_CFLAGS+=$$($1_CFLAGS_$(OPENJDK_TARGET_OS)_release)
+    $1_EXTRA_CFLAGS+=$$($1_CFLAGS_$(OPENJDK_TARGET_OS)_$(OPENJDK_TARGET_CPU)_release)
   endif
 
   # Pickup extra OPENJDK_TARGET_OS_TYPE and/or OPENJDK_TARGET_OS dependent variables for CXXFLAGS.
diff --git a/nashorn/.hgignore b/nashorn/.hgignore
index 92acdd9..28d612d 100644
--- a/nashorn/.hgignore
+++ b/nashorn/.hgignore
@@ -1,6 +1,5 @@
 syntax: glob
 
-^.hgtip
 build/*
 dist/*
 /nbproject/private/
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 86eef2f..7bf6b52 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -380,3 +380,4 @@
 a7f21ee6ed30695a6de14e74035d2857a754f62b jdk-9+144
 4a68dd740be8aa0d1a25f94985b3cb2e190ccfce jdk-9+145
 55f5a96988de8237f3ee65a69aa4a48aed9ca8d4 jdk-9+146
+9e86d6383456a1eb0298c72bb9ca363939ad90cf jdk-9+147
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
index c5f4c49..c5cb0b5 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
@@ -29,7 +29,6 @@
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJ_PKG;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.RUNTIME_PKG;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTS_PKG;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_SYMBOL;
 
@@ -111,6 +110,8 @@
 
     private boolean isOptimistic;
 
+    private boolean convertsNumericArgs;
+
     /**
      * @return the kind
      */
@@ -172,6 +173,23 @@
     }
 
     /**
+     * Check if this function converts arguments for numeric parameters to numbers
+     * so it's safe to pass booleans as 0 and 1
+     * @return true if it is safe to convert arguments to numbers
+     */
+    public boolean convertsNumericArgs() {
+        return convertsNumericArgs;
+    }
+
+    /**
+     * Tag this as a function that converts arguments for numeric params to numbers
+     * @param convertsNumericArgs if true args can be safely converted to numbers
+     */
+    public void setConvertsNumericArgs(final boolean convertsNumericArgs) {
+        this.convertsNumericArgs = convertsNumericArgs;
+    }
+
+    /**
      * Get the SpecializedFunction guard for specializations, i.e. optimistic
      * builtins
      * @return specialization, null if none
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
index bb361cc..e69f036 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
@@ -412,6 +412,7 @@
                 visitLdcInsn(linkLogicClass);
             }
             visitInsn(mi.isOptimistic() ? ICONST_1 : ICONST_0);
+            visitInsn(mi.convertsNumericArgs() ? ICONST_1 : ICONST_0);
             visitMethodInsn(INVOKESPECIAL, SPECIALIZATION_TYPE, INIT, ctor, false);
             arrayStore(TYPE_SPECIALIZATION);
         }
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
index 4a14d80..a39204d 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
@@ -210,6 +210,7 @@
                         private Where   where;
                         private boolean isSpecializedConstructor;
                         private boolean isOptimistic;
+                        private boolean convertsNumericArgs;
                         private Type    linkLogicClass = MethodGenerator.EMPTY_LINK_LOGIC_TYPE;
 
                         @Override
@@ -238,6 +239,10 @@
                             case "linkLogic":
                                 this.linkLogicClass = (Type)annotationValue;
                                 break;
+                            case "convertsNumericArgs":
+                                assert annoKind == Kind.SPECIALIZED_FUNCTION;
+                                this.convertsNumericArgs = (Boolean)annotationValue;
+                                break;
                             default:
                                 break;
                             }
@@ -298,6 +303,7 @@
                             memInfo.setLinkLogicClass(linkLogicClass);
                             memInfo.setIsSpecializedConstructor(isSpecializedConstructor);
                             memInfo.setIsOptimistic(isOptimistic);
+                            memInfo.setConvertsNumericArgs(convertsNumericArgs);
                         }
                     };
                 }
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
index 428cece..2dc560a 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
@@ -45,7 +45,6 @@
 
     // standard jdk types, methods
     static final Type TYPE_METHODHANDLE         = Type.getType(MethodHandle.class);
-    static final Type TYPE_METHODHANDLE_ARRAY   = Type.getType(MethodHandle[].class);
     static final Type TYPE_SPECIALIZATION       = Type.getType("L" + RUNTIME_PKG + "Specialization;");
     static final Type TYPE_SPECIALIZATION_ARRAY = Type.getType("[L" + RUNTIME_PKG + "Specialization;");
     static final Type TYPE_OBJECT               = Type.getType(Object.class);
@@ -60,13 +59,11 @@
     static final String INIT = "<init>";
     static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE);
 
-    static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
     static final String SPECIALIZATION_TYPE = TYPE_SPECIALIZATION.getInternalName();
-    static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.getType(boolean.class));
-    static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.getType(boolean.class));
+    static final String SPECIALIZATION_INIT2 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE);
+    static final String SPECIALIZATION_INIT3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_METHODHANDLE, TYPE_CLASS, Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE);
     static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
     static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
-    static final String STRING_TYPE = TYPE_STRING.getInternalName();
     static final String STRING_DESC = TYPE_STRING.getDescriptor();
     static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class);
     static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName();
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index 87d22bd..cbf7f29 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -28,6 +28,10 @@
   <import file="code_coverage.xml"/>
 
   <target name="load-properties">
+    <!-- set default values to run.test.jvmargs.external property -->
+    <condition property="run.test.jvmargs.external" value="">
+     <not><isset property="run.test.jvmargs.external"/></not>
+    </condition>     
     <!-- loading locally defined resources and properties. NB they owerwrite default ones defined later -->
     <property file="${user.home}/.nashorn.project.local.properties"/>
 
diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties
index 695992f..9b61ea8 100644
--- a/nashorn/make/project.properties
+++ b/nashorn/make/project.properties
@@ -154,7 +154,9 @@
     --add-exports jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp=ALL-UNNAMED \
     --add-exports jdk.scripting.nashorn/jdk.nashorn.internal.runtime.regexp.joni=ALL-UNNAMED \
     --add-exports jdk.scripting.nashorn/jdk.nashorn.tools=ALL-UNNAMED \
-    --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
+    --add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \
+    --add-opens jdk.scripting.nashorn/jdk.nashorn.internal.runtime=ALL-UNNAMED \
+    --add-opens jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv=ALL-UNNAMED
 
 meta.inf.dir=${nashorn.module.src.dir}/META-INF
 
@@ -353,6 +355,7 @@
 run.test.jvmargs.common=\
   -server \
   ${test.module.imports} \
+  ${run.test.jvmargs.external} \
   ${nashorn.override.option} \
   -Dfile.encoding=UTF-8 \
   -Duser.language=${run.test.user.language} \
diff --git a/nashorn/src/jdk.dynalink/share/classes/module-info.java b/nashorn/src/jdk.dynalink/share/classes/module-info.java
index b9abdc3..5110d01 100644
--- a/nashorn/src/jdk.dynalink/share/classes/module-info.java
+++ b/nashorn/src/jdk.dynalink/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Dynalink
+ */
 module jdk.dynalink {
     requires java.logging;
 
diff --git a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java
index 953ca18..790fc62 100644
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/module-info.java
@@ -23,6 +23,9 @@
  * questions.
  */
 
+/**
+ * Nashorn shell module
+ */
 module jdk.scripting.nashorn.shell {
     requires java.desktop;
     requires java.compiler;
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java
index b082076..b8db1b7 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java
@@ -244,7 +244,7 @@
      * @param global the global
      * @return initialized exception
      */
-    protected NashornException initEcmaError(final ScriptObject global) {
+    NashornException initEcmaError(final ScriptObject global) {
         if (ecmaError != null) {
             return this; // initialized already!
         }
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
index c4053bc..1431299 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -4066,7 +4066,7 @@
                     void loadStack() {
                         assert assignNode.getWidestOperandType() == Type.INT;
                         if (isRhsZero(binaryNode)) {
-                            loadExpressionAsType(binaryNode.lhs(), Type.INT);
+                            loadExpression(binaryNode.lhs(), TypeBounds.INT, true);
                         } else {
                             loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false);
                             method.shr();
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java
index 357689a..d311c85 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java
@@ -61,7 +61,6 @@
 import jdk.nashorn.internal.runtime.OptimisticBuiltins;
 import jdk.nashorn.internal.runtime.PropertyDescriptor;
 import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Undefined;
@@ -748,7 +747,7 @@
      * @param arg argument
      * @return resulting NativeArray
      */
-    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
+    @SpecializedFunction(linkLogic=ConcatLinkLogic.class, convertsNumericArgs = false)
     public static NativeArray concat(final Object self, final int arg) {
         final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Integer.class).copy(); //get at least an integer data copy of this data
         newData.fastPush(arg); //add an integer to its end
@@ -762,21 +761,7 @@
      * @param arg argument
      * @return resulting NativeArray
      */
-    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
-    public static NativeArray concat(final Object self, final long arg) {
-        final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Long.class).copy(); //get at least a long array data copy of this data
-        newData.fastPush(arg); //add a long at the end
-        return new NativeArray(newData);
-    }
-
-    /**
-     * ECMA 15.4.4.4 Array.prototype.concat ( [ item1 [ , item2 [ , ... ] ] ] )
-     *
-     * @param self self reference
-     * @param arg argument
-     * @return resulting NativeArray
-     */
-    @SpecializedFunction(linkLogic=ConcatLinkLogic.class)
+    @SpecializedFunction(linkLogic=ConcatLinkLogic.class, convertsNumericArgs = false)
     public static NativeArray concat(final Object self, final double arg) {
         final ContinuousArrayData newData = getContinuousArrayDataCCE(self, Double.class).copy(); //get at least a number array data copy of this data
         newData.fastPush(arg); //add a double at the end
@@ -837,13 +822,12 @@
     private static void concatToList(final ArrayList<Object> list, final Object obj) {
         final boolean isScriptArray  = isArray(obj);
         final boolean isScriptObject = isScriptArray || obj instanceof ScriptObject;
-        if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) {
+        if (isScriptArray || obj instanceof Iterable || obj instanceof JSObject || (obj != null && obj.getClass().isArray())) {
             final Iterator<Object> iter = arrayLikeIterator(obj, true);
             if (iter.hasNext()) {
                 for (int i = 0; iter.hasNext(); ++i) {
                     final Object value = iter.next();
-                    final boolean lacksIndex = obj != null && !((ScriptObject)obj).has(i);
-                    if (value == ScriptRuntime.UNDEFINED && isScriptObject && lacksIndex) {
+                    if (value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) {
                         // TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling
                         // UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE,
                         // RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it
@@ -980,7 +964,7 @@
      * @param arg a primitive to push
      * @return array length after push
      */
-    @SpecializedFunction(linkLogic=PushLinkLogic.class)
+    @SpecializedFunction(linkLogic=PushLinkLogic.class, convertsNumericArgs = false)
     public static double push(final Object self, final int arg) {
         return getContinuousArrayDataCCE(self, Integer.class).fastPush(arg);
     }
@@ -994,21 +978,7 @@
      * @param arg a primitive to push
      * @return array length after push
      */
-    @SpecializedFunction(linkLogic=PushLinkLogic.class)
-    public static double push(final Object self, final long arg) {
-        return getContinuousArrayDataCCE(self, Long.class).fastPush(arg);
-    }
-
-    /**
-     * ECMA 15.4.4.7 Array.prototype.push (args...)
-     *
-     * Primitive specialization, {@link LinkLogic}
-     *
-     * @param self self reference
-     * @param arg a primitive to push
-     * @return array length after push
-     */
-    @SpecializedFunction(linkLogic=PushLinkLogic.class)
+    @SpecializedFunction(linkLogic=PushLinkLogic.class, convertsNumericArgs = false)
     public static double push(final Object self, final double arg) {
         return getContinuousArrayDataCCE(self, Double.class).fastPush(arg);
     }
@@ -1857,15 +1827,14 @@
             }
 
             final Object arg = args[2];
-            //args[2] continuousarray or non arraydata, let past non array datas
+            // The generic version uses its own logic and ArrayLikeIterator to decide if an object should
+            // be iterated over or added as single element. To avoid duplication of code and err on the safe side
+            // we only use the specialized version if arg is either a continuous array or a JS primitive.
             if (arg instanceof NativeArray) {
-                final ContinuousArrayData argData = getContinuousArrayData(arg);
-                if (argData == null) {
-                    return false;
-                }
+                return (getContinuousArrayData(arg) != null);
             }
 
-            return true;
+            return JSType.isPrimitive(arg);
         }
     }
 
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java
index d91ffa4..25320ea 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java
@@ -539,17 +539,6 @@
     }
 
     /**
-     * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for long position
-     * @param self self reference
-     * @param pos  position in string
-     * @return number representing charcode at position
-     */
-    @SpecializedFunction(linkLogic=CharCodeAtLinkLogic.class)
-    public static int charCodeAt(final Object self, final long pos) {
-        return charCodeAt(self, (int)pos);
-    }
-
-    /**
      * ECMA 15.5.4.5 String.prototype.charCodeAt (pos) - specialized version for int position
      * @param self self reference
      * @param pos  position in string
@@ -1176,24 +1165,7 @@
     }
 
     /**
-     * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg
-     *
-     * Constructor
-     *
-     * @param newObj is this constructor invoked with the new operator
-     * @param self   self reference
-     * @param arg    the arg
-     *
-     * @return new NativeString containing the string representation of the arg
-     */
-    @SpecializedFunction(isConstructor=true)
-    public static Object constructor(final boolean newObj, final Object self, final long arg) {
-        final String str = Long.toString(arg);
-        return newObj ? newObj(str) : str;
-    }
-
-    /**
-     * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code int} arg
+     * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code double} arg
      *
      * Constructor
      *
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
index cf6daaf..b6aeaa9 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
@@ -215,4 +215,14 @@
      * @return whether this function can throw {@link UnwarrantedOptimismException}.
      */
     boolean isOptimistic() default false;
+
+    /**
+     * Is it safe to convert non-numeric arguments to numbers for this function's primitive numeric parameters?
+     * This is true for many built-in functions which expect numeric arguments, but not for those that
+     * expect generic arguments and just have specializations with numeric params to avoid boxing overhead.
+     * The default value is {@code true} because that is by far the most common case.
+     *
+     * @return true if it is safe to convert arguments to numbers
+     */
+    boolean convertsNumericArgs() default true;
 }
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java
index 05d0ab9..d862739 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java
@@ -152,6 +152,10 @@
         return null;
     }
 
+    boolean convertsNumericArgs() {
+        return isSpecialization() && specialization.convertsNumericArgs();
+    }
+
     int getFlags() {
         return flags;
     }
@@ -388,10 +392,18 @@
             int narrowWeightDelta = 0;
             int widenWeightDelta = 0;
             final int minParamsCount = Math.min(Math.min(thisParamCount, otherParamCount), callSiteParamCount);
+            final boolean convertsNumericArgs = cf.convertsNumericArgs();
             for(int i = 0; i < minParamsCount; ++i) {
-                final int callSiteParamWeight = getParamType(i, callSiteType, csVarArg).getWeight();
+                final Type callSiteParamType = getParamType(i, callSiteType, csVarArg);
+                final Type thisParamType = getParamType(i, thisType, thisVarArg);
+                if (!convertsNumericArgs && callSiteParamType.isBoolean() && thisParamType.isNumeric()) {
+                    // When an argument is converted to number by a function it is safe to "widen" booleans to numeric types.
+                    // However, we must avoid this conversion for generic functions such as Array.prototype.push.
+                    return false;
+                }
+                final int callSiteParamWeight = callSiteParamType.getWeight();
                 // Delta is negative for narrowing, positive for widening
-                final int thisParamWeightDelta = getParamType(i, thisType, thisVarArg).getWeight() - callSiteParamWeight;
+                final int thisParamWeightDelta = thisParamType.getWeight() - callSiteParamWeight;
                 final int otherParamWeightDelta = getParamType(i, otherType, otherVarArg).getWeight() - callSiteParamWeight;
                 // Only count absolute values of narrowings
                 narrowWeightDelta += Math.max(-thisParamWeightDelta, 0) - Math.max(-otherParamWeightDelta, 0);
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java
index 96bfda4..c40943b 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java
@@ -320,7 +320,7 @@
     private final WeakValueCache<CodeSource, Class<?>> anonymousHostClasses = new WeakValueCache<>();
 
     private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
-        private static final Unsafe UNSAFE = getUnsafe();
+        private static final Unsafe UNSAFE = Unsafe.getUnsafe();
         private static final String ANONYMOUS_HOST_CLASS_NAME = Compiler.SCRIPTS_PACKAGE.replace('/', '.') + ".AnonymousHost";
         private static final byte[] ANONYMOUS_HOST_CLASS_BYTES = getAnonymousHostClassBytes();
 
@@ -357,21 +357,6 @@
             cw.visitEnd();
             return cw.toByteArray();
         }
-
-        private static Unsafe getUnsafe() {
-            return AccessController.doPrivileged(new PrivilegedAction<Unsafe>() {
-                @Override
-                public Unsafe run() {
-                    try {
-                        final Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
-                        theUnsafeField.setAccessible(true);
-                        return (Unsafe)theUnsafeField.get(null);
-                    } catch (final ReflectiveOperationException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            });
-        }
     }
 
     /** Is Context global debug mode enabled ? */
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java
index c37f199..4a22352 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java
@@ -69,12 +69,12 @@
     private Module createModule(final String moduleName) {
         final Module structMod = context.getStructLoader().getModule();
         final ModuleDescriptor.Builder builder =
-            new ModuleDescriptor.Builder(moduleName)
+            ModuleDescriptor.module(moduleName)
                     .requires("java.base")
                     .requires("java.logging")
                     .requires(NASHORN_MODULE.getName())
                     .requires(structMod.getName())
-                    .conceals(SCRIPTS_PKG);
+                    .contains(SCRIPTS_PKG);
 
         if (Context.javaSqlFound) {
             builder.requires("java.sql");
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java
index 9807cc6..0a03769 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Specialization.java
@@ -36,6 +36,7 @@
     private final MethodHandle mh;
     private final Class<? extends LinkLogic> linkLogicClass;
     private final boolean isOptimistic;
+    private final boolean convertsNumericArgs;
 
     /**
      * Constructor
@@ -43,7 +44,7 @@
      * @param mh  invoker method handler
      */
     public Specialization(final MethodHandle mh) {
-        this(mh, false);
+        this(mh, false, true);
     }
 
     /**
@@ -52,9 +53,10 @@
      * @param mh  invoker method handler
      * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException}
      *   which would have to lead to a relink and return value processing
+     * @param convertsNumericArgs true if it is safe to convert arguments to numbers
      */
-    public Specialization(final MethodHandle mh, final boolean isOptimistic) {
-        this(mh, null, isOptimistic);
+    public Specialization(final MethodHandle mh, final boolean isOptimistic, final boolean convertsNumericArgs) {
+        this(mh, null, isOptimistic, convertsNumericArgs);
     }
 
     /**
@@ -65,10 +67,13 @@
      *  if this can be linked on its first encounter, which is needed as per our standard linker semantics
      * @param isOptimistic is this an optimistic native method, i.e. can it throw {@link UnwarrantedOptimismException}
      *   which would have to lead to a relink and return value processing
+     * @param convertsNumericArgs true if it is safe to convert arguments to numbers
      */
-    public Specialization(final MethodHandle mh, final Class<? extends LinkLogic> linkLogicClass, final boolean isOptimistic) {
+    public Specialization(final MethodHandle mh, final Class<? extends LinkLogic> linkLogicClass,
+                          final boolean isOptimistic, final boolean convertsNumericArgs) {
         this.mh             = mh;
         this.isOptimistic   = isOptimistic;
+        this.convertsNumericArgs = convertsNumericArgs;
         if (linkLogicClass != null) {
             //null out the "empty" link logic class for optimization purposes
             //we only use the empty instance because we can't default class annotations
@@ -110,5 +115,15 @@
         return isOptimistic;
     }
 
+    /**
+     * Check if this function converts arguments for numeric parameters to numbers
+     * so it's safe to pass booleans as 0 and 1
+     *
+     * @return true if it is safe to convert arguments to numbers
+     */
+    public boolean convertsNumericArgs() {
+        return convertsNumericArgs;
+    }
+
 }
 
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java
index be7d38b..075540a 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StructureLoader.java
@@ -63,10 +63,10 @@
 
     private Module createModule(final String moduleName) {
         final ModuleDescriptor descriptor
-                = new ModuleDescriptor.Builder(moduleName)
+                = ModuleDescriptor.module(moduleName)
                     .requires("java.base")
                     .requires(NASHORN_MODULE.getName())
-                    .conceals(SCRIPTS_PKG)
+                    .contains(SCRIPTS_PKG)
                     .build();
 
         final Module mod = Context.createModuleTrusted(descriptor, this);
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
index af6de32..6f2ee8c 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
@@ -40,9 +40,13 @@
 import jdk.dynalink.linker.LinkerServices;
 import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
 import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.objects.Global;
 
 /**
  * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
@@ -142,9 +146,9 @@
     }
 
     private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
-        MethodHandle mh = JSOBJECT_CALL;
+        MethodHandle mh = NashornCallSiteDescriptor.isScope(desc)? JSOBJECT_SCOPE_CALL : JSOBJECT_CALL;
         if (NashornCallSiteDescriptor.isApplyToCall(desc)) {
-            mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL);
+            mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, mh);
         }
         final MethodType type = desc.getMethodType();
         mh = type.parameterType(type.parameterCount() - 1) == Object[].class ?
@@ -215,6 +219,19 @@
         }
     }
 
+    // This is used when a JSObject is called as scope call to do undefined -> Global this translation.
+    @SuppressWarnings("unused")
+    private static Object jsObjectScopeCall(final JSObject jsObj, final Object thiz, final Object[] args) {
+        final Object modifiedThiz;
+        if (thiz == ScriptRuntime.UNDEFINED && !jsObj.isStrictFunction()) {
+            final Global global = Context.getGlobal();
+            modifiedThiz = ScriptObjectMirror.wrap(global, global);
+        } else {
+            modifiedThiz = thiz;
+        }
+        return jsObj.call(modifiedThiz, args);
+    }
+
     private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
 
     // method handles of the current class
@@ -226,6 +243,7 @@
     private static final MethodHandle JSOBJECT_GETMEMBER     = findJSObjectMH_V("getMember", Object.class, String.class);
     private static final MethodHandle JSOBJECT_SETMEMBER     = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class);
     private static final MethodHandle JSOBJECT_CALL          = findJSObjectMH_V("call", Object.class, Object.class, Object[].class);
+    private static final MethodHandle JSOBJECT_SCOPE_CALL    = findOwnMH_S("jsObjectScopeCall", Object.class, JSObject.class, Object.class, Object[].class);
     private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class);
     private static final MethodHandle JSOBJECT_NEW           = findJSObjectMH_V("newObject", Object.class, Object[].class);
 
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java
index cc9e76e..b3e165a 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/ModuleGraphManipulator.java
@@ -61,8 +61,8 @@
             throw new IllegalStateException(myClass + " loaded by wrong loader!");
         }
 
-        // From this module add a qualified export to nashorn module
-        MY_MODULE.addExports(MY_PKG_NAME, nashornModule);
+        // open package to nashorn module
+        MY_MODULE.addOpens(MY_PKG_NAME, nashornModule);
     }
 
     // The following method is reflectively invoked from Nashorn
diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java b/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java
index ab18e22..9a7dcaf 100644
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/module-info.java
@@ -23,9 +23,12 @@
  * questions.
  */
 
+/**
+ * Nashorn
+ */
 module jdk.scripting.nashorn {
     requires java.logging;
-    requires public java.scripting;
+    requires transitive java.scripting;
     requires jdk.dynalink;
 
     exports jdk.nashorn.api.scripting;
diff --git a/nashorn/test/TEST.ROOT b/nashorn/test/TEST.ROOT
index f8dabb2..08e6c7f 100644
--- a/nashorn/test/TEST.ROOT
+++ b/nashorn/test/TEST.ROOT
@@ -8,7 +8,7 @@
 groups=TEST.groups
 
 # Minimum jtreg version
-requiredVersion=4.2 b03
+requiredVersion=4.2 b04
 
 # Use new module options
 useNewOptions=true
diff --git a/nashorn/test/script/basic/JDK-8161579.js b/nashorn/test/script/basic/JDK-8161579.js
new file mode 100644
index 0000000..cc52c17
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8161579.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8161579: Array-like AbstractJSObject-based instance not treated as array by native array functions
+ *
+ * @test
+ * @run
+ */
+
+
+var AbstractJSObject = Java.type("jdk.nashorn.api.scripting.AbstractJSObject");
+var JavaStringArray = Java.type("java.lang.String[]");
+var JavaArrayList = Java.type("java.util.ArrayList");
+
+var arrayLikeJSObject = new AbstractJSObject() {
+    hasMember: function(name) { return name == "length"; },
+    getMember: function(name) { return name == "length" ? 3 : null; },
+    hasSlot: function(slot) { return slot >= 0 && slot <= 2; },
+    getSlot: function(slot) { return "abc"[slot]; },
+    isArray: function() { return true; }
+}
+
+var javaStringArray = new JavaStringArray(3);
+javaStringArray[0] = "x";
+javaStringArray[1] = "y";
+javaStringArray[2] = "z";
+
+var javaArrayList = new JavaArrayList();
+javaArrayList.add("i");
+javaArrayList.add("j");
+javaArrayList.add("k");
+
+Assert.assertEquals([1, 2, 3].concat(arrayLikeJSObject).join(), "1,2,3,a,b,c");
+Assert.assertEquals([1, 2, 3].concat(javaStringArray).join(), "1,2,3,x,y,z");
+Assert.assertEquals([1, 2, 3].concat(javaArrayList).join(), "1,2,3,i,j,k");
+Assert.assertEquals([1, 2, 3].concat("foo").join(), "1,2,3,foo");
+Assert.assertEquals([1, 2, 3].concat(4).join(), "1,2,3,4");
+Assert.assertEquals([1, 2, 3].concat(false).join(), "1,2,3,false");
+
diff --git a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java b/nashorn/test/script/basic/JDK-8170322.js
similarity index 70%
copy from hotspot/test/serviceability/jdwp/JdwpCanReadReply.java
copy to nashorn/test/script/basic/JDK-8170322.js
index 438f741..45ee265 100644
--- a/hotspot/test/serviceability/jdwp/JdwpCanReadReply.java
+++ b/nashorn/test/script/basic/JDK-8170322.js
@@ -1,41 +1,42 @@
 /*
  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.
- *
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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.DataInputStream;
-import java.io.IOException;
 
 /**
- * The reply to the JDWP CANREAD command
+ * JDK-8170322: Specialized functions convert booleans to numbers
+ *
+ * @test
+ * @run
  */
-public class JdwpCanReadReply extends JdwpReply {
 
-    private boolean canRead;
+var array = [];
+array.push(true);
+array.push(false);
 
-    protected void parseData(DataInputStream ds) throws IOException {
-        canRead = (ds.read() != 0);
-    }
+Assert.assertTrue([].concat(true)[0] === true);
+Assert.assertTrue([].concat(false)[0] === false);
 
-    public boolean canRead() {
-        return canRead;
-    }
+Assert.assertTrue(array[0] === true);
+Assert.assertTrue(array[1] === false);
 
-}
+Assert.assertTrue("foo".charAt(false) === 'f');
+Assert.assertTrue("foo".charAt(true) === 'o');
diff --git a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java b/nashorn/test/script/basic/JDK-8170594.js
similarity index 69%
copy from langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
copy to nashorn/test/script/basic/JDK-8170594.js
index 789cdb9..6365500 100644
--- a/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java
+++ b/nashorn/test/script/basic/JDK-8170594.js
@@ -1,33 +1,45 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute it and/or modify it
  * 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 p7;
+/**
+ * JDK-8170594: >>>=0 generates invalid bytecode for BaseNode LHS
+ *
+ * @test
+ * @run
+ */
 
-// Only use classes in unsafe and m6 modules with no
-// direct or indirect dependency on sun.misc.Unsafe
-public class Main {
-    public static void main(String... args) {
-        p6.safe.Lib.doit();
-        org.safe.Lib.doit();
-    }
-}
+var obj1 = {x: "100"};
+(function (o, p) {
+ if (p) {
+   o.x >>>= 0;
+ }
+})(obj1, true)
+Assert.assertTrue(obj1.x === 100)
+
+var obj2 = ["100"];
+(function (o, p) {
+ if (p) {
+   o[0] >>>= 0;
+ }
+})(obj2, true)
+Assert.assertTrue(obj2[0] === 100)
diff --git a/nashorn/test/script/currently-failing/JDK-8130127.js.EXPECTED b/nashorn/test/script/currently-failing/JDK-8130127.js.EXPECTED
deleted file mode 100644
index 0362052..0000000
--- a/nashorn/test/script/currently-failing/JDK-8130127.js.EXPECTED
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-hello
-
diff --git a/nashorn/test/script/nosecurity/JDK-8044798.js b/nashorn/test/script/nosecurity/JDK-8044798.js
index dcf1796..77e67f5 100644
--- a/nashorn/test/script/nosecurity/JDK-8044798.js
+++ b/nashorn/test/script/nosecurity/JDK-8044798.js
@@ -33,13 +33,14 @@
 
 var Arrays = Java.type("java.util.Arrays");
 var CharArray = Java.type("char[]");
+var Reflector = Java.type("jdk.nashorn.test.models.Reflector");
 var DebuggerSupport = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport");
 var DebuggerValueDesc = Java.type("jdk.nashorn.internal.runtime.DebuggerSupport.DebuggerValueDesc");
 
 var valueDescFields = DebuggerValueDesc.class.declaredFields;
 Arrays.sort(valueDescFields, function(f1, f2) f1.name.compareTo(f2.name));
 for each (var f in valueDescFields) {
-    f.accessible = true;
+    Reflector.setAccessible(f);
 }
 
 var debuggerSupportMethods = DebuggerSupport.class.declaredMethods;
@@ -49,7 +50,7 @@
 var getSourceInfoMethod, valueAsStringMethod;
 
 for each (var m in debuggerSupportMethods) {
-    m.accessible = true;
+    Reflector.setAccessible(m);
     switch (m.name) {
         case "eval":
             evalMethod = m;
@@ -129,10 +130,10 @@
 // private compile method of Context class
 var compileMethod = contextCls.getDeclaredMethod("compile",
                 sourceCls, errorMgrCls, booleanCls, booleanCls);
-compileMethod.accessible = true;
+Reflector.setAccessible(compileMethod);
 
 var getContextMethod = contextCls.getMethod("getContext");
-getContextMethod.accessible = true;
+Reflector.setAccessible(getContextMethod);
 
 var sourceForMethod = sourceCls.getMethod("sourceFor", stringCls, stringCls);
 var scriptCls = compileMethod.invoke(getContextMethod.invoke(null),
@@ -149,7 +150,7 @@
 
 print("Source info");
 for each (var f in srcInfoFields) {
-    f.accessible = true;
+    Reflector.setAccessible(f);
     var fieldValue = f.get(srcInfo);
     if (fieldValue instanceof CharArray) {
         fieldValue = new java.lang.String(fieldValue);
diff --git a/nashorn/test/script/currently-failing/JDK-8130127.js b/nashorn/test/script/nosecurity/JDK-8130127.js
similarity index 93%
rename from nashorn/test/script/currently-failing/JDK-8130127.js
rename to nashorn/test/script/nosecurity/JDK-8130127.js
index 55b56d1..7eb815f 100644
--- a/nashorn/test/script/currently-failing/JDK-8130127.js
+++ b/nashorn/test/script/nosecurity/JDK-8130127.js
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,5 +51,5 @@
 print($EXEC(jjsCmd, undefined))
 print($EXEC(jjsCmd, ""))
 
-print($EXEC(jjs, "print('hello')"))
+print($EXEC(jjs, "print('hello')\n"))
 
diff --git a/nashorn/test/script/nosecurity/JDK-8130127.js.EXPECTED b/nashorn/test/script/nosecurity/JDK-8130127.js.EXPECTED
new file mode 100644
index 0000000..b2debcf
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8130127.js.EXPECTED
@@ -0,0 +1,7 @@
+
+
+
+
+jjs> print('hello')
+hello
+jjs> 
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java
index 3998261..f43c0db 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java
@@ -41,6 +41,7 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.AbstractJSObject;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import org.testng.annotations.Test;
@@ -389,4 +390,41 @@
         assertTrue(func.isFunction());
         assertEquals(func.call(e.eval("this"), "hello"), "hello world");
     }
+
+    // @bug 8170565: JSObject call() is passed undefined for the argument 'thiz'
+    @Test
+    public void jsObjectThisTest() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine e = engineManager.getEngineByName("nashorn");
+        e.put("func", new AbstractJSObject() {
+            @Override
+            public boolean isFunction() { return true; }
+
+            @Override
+            public Object call(Object thiz, Object...args) {
+                return thiz;
+            }
+        });
+
+        assertTrue((boolean)e.eval("func() === this"));
+
+        // check that there is no blind undefined->Global translation!
+        assertTrue((boolean)e.eval("typeof(Function.prototype.call.call(func, undefined)) == 'undefined'"));
+
+        // make sure that strict functions don't get translated this for scope calls!
+        e.put("sfunc", new AbstractJSObject() {
+            @Override
+            public boolean isFunction() { return true; }
+
+            @Override
+            public boolean isStrictFunction() { return true; }
+
+            @Override
+            public Object call(Object thiz, Object...args) {
+                return thiz;
+            }
+        });
+
+        assertTrue((boolean)e.eval("typeof sfunc() == 'undefined'"));
+    }
 }
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java
index b34e105..9e2dc7d 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/BignumTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
  * Bignum class tests
  *
  * @test
- * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv:open
  * @run testng jdk.nashorn.internal.runtime.doubleconv.test.BignumTest
  */
 @SuppressWarnings("javadoc")
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java
index 5432e53..662e380 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/doubleconv/test/DiyFpTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
  * DiyFp class tests
  *
  * @test
- * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv
+ * @modules jdk.scripting.nashorn/jdk.nashorn.internal.runtime.doubleconv:open
  * @run testng jdk.nashorn.internal.runtime.doubleconv.test.DiyFpTest
  */
 @SuppressWarnings("javadoc")
diff --git a/nashorn/test/src/jdk/nashorn/test/models/Reflector.java b/nashorn/test/src/jdk/nashorn/test/models/Reflector.java
index decdcf3..9722694 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/Reflector.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/Reflector.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.test.models;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Module;
@@ -42,6 +43,22 @@
     private Reflector() {}
     private static final Module NASHORN_MOD = Context.class.getModule();
 
+    public static void setAccessible(Executable e) {
+        if (e.getDeclaringClass().getModule() != NASHORN_MOD) {
+            throw new RuntimeException(e + " is not from Nashorn module");
+        }
+
+        e.setAccessible(true);
+    }
+
+    public static void setAccessible(Field f) {
+        if (f.getDeclaringClass().getModule() != NASHORN_MOD) {
+            throw new RuntimeException(f + " is not from Nashorn module");
+        }
+
+        f.setAccessible(true);
+    }
+
     public static Object invoke(final Method m, final Object self, final Object...args) {
         if (m.getDeclaringClass().getModule() != NASHORN_MOD) {
             throw new RuntimeException(m + " is not from Nashorn module");
diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java
index 9d3c387..c01657f 100644
--- a/test/lib/sun/hotspot/WhiteBox.java
+++ b/test/lib/sun/hotspot/WhiteBox.java
@@ -453,8 +453,6 @@
                                   Object[] packages);
   public native void AddModuleExports(Object from_module, String pkg, Object to_module);
   public native void AddReadsModule(Object from_module, Object source_module);
-  public native boolean CanReadModule(Object asking_module, Object source_module);
-  public native boolean IsExportedToModule(Object from_module, String pkg, Object to_module);
   public native void AddModulePackage(Object module, String pkg);
   public native void AddModuleExportsToAllUnnamed(Object module, String pkg);
   public native void AddModuleExportsToAll(Object module, String pkg);